【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※マルチポスト(多重投稿)は慎んで!

 詳しくはこちら



 本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール   掲示板2こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.20095

重複しない数値を固定長で返したい
投稿者---wonderwall(2005/02/22 14:31:17)


はじめまして。初心者でどうしても解決できないので書き込みさせていただきました。
どなたか教えてください。

<処理>
最大7桁の値を重複チェックを行います。
重複した数値は1つのみを有効とします。
7桁になっていない場合は、不足をFで補い値を返す。

例えば
1122331という入力された場合は、123FFFFと返したいのです。

アドバイスをお願いいたします。

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

int main(int ac, char *av[])
{
int i, j, ke, wk, len, len2;
char buff[64];

wk=7; /*7digits */

/* param check*/
if (ac < 2) {
printf("1\n");
exit(0);
}

len = strlen(av[1]);
printf("len=%d\n",len);

/* number check 0-9 */
for (i = 0; i< len; i++) {
printf("i=%d\n",i);
if (*(av[1]+i) < 0x30 || *(av[1]+i) > 0x39) {
printf("1\n");
exit(0);
}
}

memset(buff, 0x00, 7);
printf("afterinit len=%d\n",len);
printf("buff=%s\n",buff);
for (i = 0; i < len; i++){
len2 = strlen(buff);
printf("For len2=%d\n",len2);
for (j = 0; j < len2; j++){
if (memcmp(buff+j, av[1]+i, 1) == 0){
break;
}
}
if (memcmp(buff+j, av[1]+i, 1) == 0){
continue;
}
memcpy(buff+len2, av[1]+i, 1);
}

printf("len2=%d\n",len2);
printf("j=%d\n",i);
if (j < 7){
ke = 7 - j;
printf("ke=%d\n",ke);
memset(buff+len2,0x46,ke);
}
printf("%s\n",buff);
exit(0);
}



この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:重複しない数値を固定長で返したい 20096 επιστημη 2005/02/22 14:53:53
<子記事> Re:重複しない数値を固定長で返したい 20097 Blue 2005/02/22 15:08:06
<子記事> Re:重複しない数値を固定長で返したい 20101 もあ 2005/02/22 16:02:01


No.20096

Re:重複しない数値を固定長で返したい
投稿者---επιστημη(2005/02/22 14:53:53)


>最大7桁の値を重複チェックを行います。
>重複した数値は1つのみを有効とします。
>7桁になっていない場合は、不足をFで補い値を返す。
>
>例えば
>1122331という入力された場合は、123FFFFと返したいのです。

1. [0]〜[9]の10個の箱を用意する。
2. 入力を順にたどって:
2.1 その番号を持つ箱が空なら、その番号を出力する
2.2 その番号を持つ箱を満たす
3. 足りない桁の分、Fを出力する



この投稿にコメントする

削除パスワード

No.20097

Re:重複しない数値を固定長で返したい
投稿者---Blue(2005/02/22 15:08:06)


基本的には 結果文字列に 存在したら追加しない、存在しなかったら追加する
という処理になると思います。

文字存在チェックは string.h の strchr を使えば楽にできます。
(地道にループでまわしてもOK)

# main関数はexitでおわるよりreturnでおわるほうがいいような気がします。




この投稿にコメントする

削除パスワード

No.20112

Re:重複しない数値を固定長で返したい
投稿者---Blue(2005/02/22 17:49:05)


1〜10のフラグのほうでやるっぽいので自分の案のソースを載せます。
参考にしてください。

#include <string.h> #include <stdlib.h> #include <stdio.h> #define SIZE 7 /* 結果文字列長 */ int main( int argc, char* argv[] ) { char szResult[ SIZE + 1 ] = { 0 }; /* 結果文字列 */ char cCheck; /* 入力文字チェック用文字 */ int nIndex = 0; /* 結果文字列登録インデックス */ int nLoop; /* ループ用変数 */ /* 入力文字が指定されていない場合 */ if ( argc != 2 ) { puts( "入力文字が指定されていません。" ); return EXIT_FAILURE; } /* 入力文字が7文字を超えている場合 */ if ( strlen( argv[ 1 ] ) > SIZE ) { puts( "入力文字が7文字を超えています。" ); return EXIT_FAILURE; } /* 入力文字列のチェックと登録 */ for ( nLoop = 0; nLoop < SIZE; nLoop++ ) { cCheck = *( argv[ 1 ] + nLoop ); /* 数字でない場合 */ if ( ( cCheck < '0' ) && ( cCheck > '9' ) ) { puts( "入力文字に数字でない文字が設定されています。" ); return EXIT_FAILURE; } /* 登録済みでない場合 */ if ( strchr( szResult, cCheck ) == NULL ) { szResult[ nIndex ] = cCheck; nIndex++; } } /* あまった領域を F で埋める */ for ( nLoop = nIndex; nLoop < SIZE; nLoop++ ) { szResult[ nLoop ] = 'F'; } printf( "入力 : %s\n", argv[ 1 ] ); printf( "結果 : %s\n", szResult ); return EXIT_SUCCESS; }




この投稿にコメントする

削除パスワード

No.20114

Re:重複しない数値を固定長で返したい
投稿者---monkey(2005/02/22 18:12:59)


ツッコミばかりで申し訳ありませんが

        /* 数字でない場合 */
        if ( ( cCheck < '0' ) && ( cCheck > '9' ) )
        {

は

        if ( ( cCheck < '0' ) || ( cCheck > '9' ) )

のケアレスミスと思われます.



この投稿にコメントする

削除パスワード

No.20117

Re:重複しない数値を固定長で返したい
投稿者---Blue(2005/02/22 19:55:41)


ツッコミ感謝します。
もう一個ミスってるとこあるんですよね。(まだあるかもw)

>    /* 入力文字列のチェックと登録 */
>    for ( nLoop = 0; nLoop < SIZE; nLoop++ )
    for ( nLoop = 0; nLoop < strlen( argv[ 1 ] ); nLoop++ )
    (もしくはfor文のなかで if ( cCheck == NULL ) break; )

でした。このままだとまともに動かないですね。

/(x x /)ごめんちゃい



この投稿にコメントする

削除パスワード

No.20119

Re:重複しない数値を固定長で返したい
投稿者---かずま(2005/02/23 02:13:06)


> ツッコミ感謝します。

>    for ( nLoop = 0; nLoop < strlen( argv[ 1 ] ); nLoop++ )

たしかにこれで動くでしょう。しかし、長さの変化しない argv[1] の
長さを何度も何度も数えさせることに私は不快感を覚えます。


>    (もしくはfor文のなかで if ( cCheck == NULL ) break; )

たしかにこれで動くでしょう。しかし、規格書 ISO/IEC 9899:1999 の
7.17 Common definitions <stddef.h> に、

      NULL
  which expands to an implementation-defined null pointer constant; and

と記述されている NULL を、ポインタではない cCheck と比較していることに
私は不快感を覚えます。

こんなツッコミでも歓迎しますか?

では、私もツッコミどころ満載のプログラムを示します。

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

int main(int argc, char *argv[])
{
    int c, i, j = 0;  char buf[7], f[10] = "";

    if (argc != 2) puts("1"), exit(1);
    for (i = 0; c = argv[1][i]; i++) {
        if (i >= 7 || c < '0' || c > '9') puts("2"), exit(2);
        if (!f[c-'0']) buf[j++] = c, f[c-'0'] = 1;
    }
    printf("%.*s%.*s\n", j, buf, 7-j, "FFFFFFF");
    return 0;
}



この投稿にコメントする

削除パスワード

No.20123

Re:重複しない数値を固定長で返したい
投稿者---Blue(2005/02/23 08:40:06)


>
>たしかにこれで動くでしょう。しかし、長さの変化しない argv[1] の
>長さを何度も何度も数えさせることに私は不快感を覚えます。
>
>
>>    (もしくはfor文のなかで if ( cCheck == NULL ) break; )
>
>たしかにこれで動くでしょう。しかし、規格書 ISO/IEC 9899:1999 の
>7.17 Common definitions <stddef.h> に、
>
>     NULL
>  which expands to an implementation-defined null pointer constant; and
>
>と記述されている NULL を、ポインタではない cCheck と比較していることに
>私は不快感を覚えます。

for ( nLoop = 0; nLoop < strlen( argv[ 1 ] ); nLoop++ )
は ほんとは
const int nLength = strlen( argc[ 1 ] );
を最初に宣言してから7文字以下の文字かどうかのチェックとループの条件に使うべきでしたが、
修正箇所が多すぎるのでその様に書きました。

if ( cCheck == NULL ) break;
は指摘のとおり
if ( cCheck == '\0' ) break;
にしたほうがよかったです。




この投稿にコメントする

削除パスワード

No.20124

Re:重複しない数値を固定長で返したい
投稿者---wonderwall(2005/02/23 11:15:26)


たくさんのご意見ありがとうございます。
こんなに多くのアドバイスをいただけるとは感激です。

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

><pre><font color="darkblue">>
>たしかにこれで動くでしょう。しかし、長さの変化しない argv[1] の
>長さを何度も何度も数えさせることに私は不快感を覚えます。
>
>
>> (もしくはfor文のなかで if ( cCheck == NULL ) break; )
>
>たしかにこれで動くでしょう。しかし、規格書 ISO/IEC 9899:1999 の
>7.17 Common definitions <stddef.h> に、
>
> NULL
> which expands to an implementation-defined null pointer constant; and
>
>と記述されている NULL を、ポインタではない cCheck と比較していることに
>私は不快感を覚えます。</font>

for ( nLoop = 0; nLoop < strlen( argv[ 1 ] ); nLoop++ )
は ほんとは
const int nLength = strlen( argc[ 1 ] );
を最初に宣言してから7文字以下の文字かどうかのチェックとループの条件に使うべきでしたが、
修正箇所が多すぎるのでその様に書きました。

if ( cCheck == NULL ) break;
は指摘のとおり
if ( cCheck == '\0' ) break;
にしたほうがよかったです。

</pre>



この投稿にコメントする

削除パスワード

No.20101

Re:重複しない数値を固定長で返したい
投稿者---もあ(2005/02/22 16:02:01)


こんにちわ。
参考にでもなればどうぞ。

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

int main(int argc, char* argv[])
{
    int i, len, data, cnt;
    char    buff[8] = "";
    int  flg[8];

    if (argc < 2) {
        printf("PARAMETER ERROR\n");
        return(-1);
    }

    len = strlen(argv[1]);
    if (7 < len) {
        printf("INPUT DATA ERROR\n");
        return(-1);
    }
    printf("INPUT DATA = %s : Length = %d\n", argv[1], len);
    strcpy(buff, argv[1]);

    memset(flg, 0x00, sizeof(flg));
    for (i = 0, cnt = 0; i < len; i++) {

        if ((buff[i] < 0x30) || (0x39 < buff[i])) {
            printf("INPUT DATA IS NOT NUMBER\n");
            return(-1);
        }
        data = buff[i] - 0x30;
        if (0 == flg[data]) {
            printf("%d", data);
            flg[data] = 1;
            cnt++;
        }

    }

    for (i = cnt; i < 7;i++) {
        printf("F");
    }
    printf("\n");
    return(0);

} 



この投稿にコメントする

削除パスワード

No.20105

Re:重複しない数値を固定長で返したい
投稿者---もあ(2005/02/22 16:29:11)


>こんにちわ。
>参考にでもなればどうぞ。

配列の数間違えました。
flg[8]→flg[10]

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

int main(int argc, char* argv[])
{
int i, len, data, cnt;
char buff[8] = "";
int flg[8];

if (argc < 2) {
printf("PARAMETER ERROR\n");
return(-1);
}

len = strlen(argv[1]);
if (7 < len) {
printf("INPUT DATA ERROR\n");
return(-1);
}
printf("INPUT DATA = %s : Length = %d\n", argv[1], len);
strcpy(buff, argv[1]);

memset(flg, 0x00, sizeof(flg));
for (i = 0, cnt = 0; i < len; i++) {

if ((buff[i] < 0x30) || (0x39 < buff[i])) {
printf("INPUT DATA IS NOT NUMBER\n");
return(-1);
}
data = buff[i] - 0x30;
if (0 == flg[data]) {
printf("%d", data);
flg[data] = 1;
cnt++;
}

}

for (i = cnt; i < 7;i++) {
printf("F");
}
printf("\n");
return(0);

}
</pre>



この投稿にコメントする

削除パスワード

No.20110

Re:重複しない数値を固定長で返したい
投稿者---wonderwall(2005/02/22 17:31:28)


アドバイスありがとうございます。
早速動作確認をしてみましたらうまくでき感謝しています。
ただひとつ疑問があるのですが、

>配列の数間違えました。
>flg[8]→flg[10]


これはなぜ「10」なのでしょうか??
初心者名疑問で申し訳ありませんが、教えてください。

他にもアドバイスいただいた方
ほんとうにありがとうございます。

>>こんにちわ。
>>参考にでもなればどうぞ。
>
>配列の数間違えました。
>flg[8]→flg[10]
>
>><pre>#include <stdio.h>
>#include <string.h>
>
>int main(int argc, char* argv[])
>{
> int i, len, data, cnt;
> char buff[8] = "";
> int flg[8];
>
> if (argc < 2) {
> printf("PARAMETER ERROR\n");
> return(-1);
> }
>
> len = strlen(argv[1]);
> if (7 < len) {
> printf("INPUT DATA ERROR\n");
> return(-1);
> }
> printf("INPUT DATA = %s : Length = %d\n", argv[1], len);
> strcpy(buff, argv[1]);
>
> memset(flg, 0x00, sizeof(flg));
> for (i = 0, cnt = 0; i < len; i++) {
>
> if ((buff[i] < 0x30) || (0x39 < buff[i])) {
> printf("INPUT DATA IS NOT NUMBER\n");
> return(-1);
> }
> data = buff[i] - 0x30;
> if (0 == flg[data]) {
> printf("%d", data);
> flg[data] = 1;
> cnt++;
> }
>
> }
>
> for (i = cnt; i < 7;i++) {
> printf("F");
> }
> printf("\n");
> return(0);
>
>}
></pre>




この投稿にコメントする

削除パスワード

No.20113

Re:重複しない数値を固定長で返したい
投稿者---επιστημη(2005/02/22 17:52:52)


>>配列の数間違えました。
>>flg[8]→flg[10]
>↑
>これはなぜ「10」なのでしょうか??

0〜9の '10個の数' が既出か否かを覚えておくため。



この投稿にコメントする

削除パスワード

No.20116

Re:重複しない数値を固定長で返したい
投稿者---もあ(2005/02/22 19:18:17)


こんばんわ。

>>>配列の数間違えました。
>>>flg[8]→flg[10]
>>↑
>>これはなぜ「10」なのでしょうか??
>
>0〜9の '10個の数' が既出か否かを覚えておくため。

επιστημηさんの仰るとおりです。
ためしにflg[8]として、"9"を入力し、実行すると成功する場合と失敗する場合があるはずです。(おおむね失敗するはず)
これは、定義されていないflg[9]に不定値が設定されており、9を既出と認識するからです。
しかし、それ以前に領域を確保していないflg[9]に値を設定するため、メモリ領域を破壊しています。
ですから"int flg[8]"ではなく"int flg[10]"としなければなりません。(配列は0〜9の10個必要)
(この"int flg[8]"というミスは致命的なわけです)

ちなみに私のεπιστημηさんのアイデアを少し(全部)パクッたソースは文字を一度数値に変換しています。
文字列操作という意味では私のソースは適切ではありません。
それにバグありますしね。("01122a"を入力すると。。。)
#明らかにεπιστημηさんのアイデアを意識しているのにお断りを忘れました。失礼いたしました。

最後に、プログラムは「ソースを記述」すること(今回では私のソース)よりもむしろ
「要件をどのようにソースで表す」か(今回ではεπιστημηさんやBlueさんのアイデア)を考える方が重要です。(かといって、ソースをないがしろにしてもいけませんが)
参考までに。。。



この投稿にコメントする

削除パスワード

No.20129

Re:重複しない数値を固定長で返したい
投稿者---wonderwall(2005/02/23 13:32:15)


お世話になっております。
詳しいご説明ありがとうございました。

もあさんのソースを詳しく勉強させていだただきまして、確認したのですが、
新たな疑問があります。

memset(flg, 0x00, sizeof(flg));

ここをprintfすると、
printf("flag=%d",flag);
flag=6618552という値が入っているようです。
0x00なのでnullが入っているものと思ったのですが。

あと一つ
data = buff[i] - 0x30;
if (0 == flg[data]) {
printf("%d", data);
flg[data] = 1;
cnt++;
}

この部分ですが、if (0 == flg[data]とありますが、
0はいつ入るのでしょうか?
初期化するときですか?

たびたびの質問で申し訳ありません。
よろしくお願いいたします。




>こんばんわ。
>
>>>>配列の数間違えました。
>>>>flg[8]→flg[10]
>>>↑
>>>これはなぜ「10」なのでしょうか??
>>
>>0〜9の '10個の数' が既出か否かを覚えておくため。
>
>επιστημηさんの仰るとおりです。
>ためしにflg[8]として、"9"を入力し、実行すると成功する場合と失敗する場合があるはずです。(おおむね失敗するはず)
>これは、定義されていないflg[9]に不定値が設定されており、9を既出と認識するからです。
>しかし、それ以前に領域を確保していないflg[9]に値を設定するため、メモリ領域を破壊しています。
>ですから"int flg[8]"ではなく"int flg[10]"としなければなりません。(配列は0〜9の10個必要)
>(この"int flg[8]"というミスは致命的なわけです)
>
>ちなみに私のεπιστημηさんのアイデアを少し(全部)パクッたソースは文字を一度数値に変換しています。
>文字列操作という意味では私のソースは適切ではありません。
>それにバグありますしね。("01122a"を入力すると。。。)
>#明らかにεπιστημηさんのアイデアを意識しているのにお断りを忘れました。失礼いたしました。
>
>最後に、プログラムは「ソースを記述」すること(今回では私のソース)よりもむしろ
>「要件をどのようにソースで表す」か(今回ではεπιστημηさんやBlueさんのアイデア)を考える方が重要です。(かといって、ソースをないがしろにしてもいけませんが)
>参考までに。。。




この投稿にコメントする

削除パスワード

No.20130

Re:重複しない数値を固定長で返したい
投稿者---REE(2005/02/23 14:45:46)


>新たな疑問があります。
>
>memset(flg, 0x00, sizeof(flg));
>
>ここをprintfすると、
>printf("flag=%d",flag);
>flag=6618552という値が入っているようです。
>0x00なのでnullが入っているものと思ったのですが。

memsetで設定しているのは、flg[0]〜flg[9]の値ですが、ここで表示しているのはflgの値です。
配列の仕組みについて、勉強しなおしてみてください。
以下のように確認してみてください。

printf("flg[0]=%d",flag[0]);

>この部分ですが、if (0 == flg[data]とありますが、
>0はいつ入るのでしょうか?

ということで、上記のmemsetで0クリアされています。


【掲示板ご利用上の注意】
※返信の引用は最小限に!

今回の末尾の引用は、質問内容とは無関係ですので、必要ありません。


この投稿にコメントする

削除パスワード

No.20107

Re:重複しない数値を固定長で返したい
投稿者---επιστημη(2005/02/22 16:52:21)


> 参考にでもなればどうぞ。
/*
 * C++ version
 */
#include <string>
#include <cassert>
#include <algorithm>
#include <iomanip>

using namespace std;

string f(const string& input) {
  if ( input.size() > 7) return "";
  string result;
  for ( int i = 0; i < input.size(); ++i ) {
    char ch = input[i];
    if ( ch < '0' || ch > '9' ) return "";
    if ( find(result.begin(), result.end(), ch) == result.end() ) {
      result += ch;
    }
  }
  while ( result.size() < 7 ) {
    result += 'F';
  }
  return result;
}

void trial(const string& input) {
  string result = f(input);
  cout << setw(7) << input << " -> " 
       << (result.empty() ? "ERROR" : result) << endl;
}

int main() {
  trial("123456789");
  trial("123a");
  trial("1234567");
  trial("1111111");
  trial("1122331");
  return 0;
}

----- output -----
123456789 -> ERROR
   123a -> ERROR
1234567 -> 1234567
1111111 -> 1FFFFFF
1122331 -> 123FFFF




この投稿にコメントする

削除パスワード

No.20109

Re:重複しない数値を固定長で返したい
投稿者---monkey(2005/02/22 17:22:00)


#include <iostream>

をお忘れのような...



この投稿にコメントする

削除パスワード

No.20111

Re:重複しない数値を固定長で返したい
投稿者---επιστημη(2005/02/22 17:33:06)


いたたたた。的確なツッコミに感謝。



この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧