C言語関係掲示板

過去ログ

No705 表計算ソフトの処理をCで

[戻る] [ホームページ]
No.8432

宜しかったら教えて下さい
投稿者---三浦忠(2003/07/16 16:09:12)
http://mi328.hp.infoseek.co.jp/


こんにちは
表計算ソフトの手動入力で今までやって来たのですが、
処理する情報が膨れ上がってしまい、手動では対応できなくなって
しまいました。

そこでC言語の本を数冊ほど読んでみたのですが、
データの処理に必要な方法を見つける事ができませんでした。

コンパイルしてみましたが、うまく表示されませんでした。
そこで宜しかったらデータの処理の方法(プログラムの書き方)
を教えて頂きたいのです。

処理したい物は下記のような文字列です。


012 345/678/901全角 234 567


処理したい方法は下記です。
1、
上記の文字列の中から、まず右から

012 345 678 901

を抜き出します。( ”/ ”と”全角”は必要ありません)


2、
そしてこれらの数字をバラバラにして1つ1つを足していきます。
0+1+2+3+4+5+6+7+8+9+0+1=46


3、
合計が出た場合は、その数字をまたバラバラにして1ケタの数字に
なるまで足していきます。
(ただし、”11””22”の数字が出た場合は、加算は終了します)

0+1+2+3+4+5+6+7+8+9+0+1=46
4+6=10
1+0=1


4、
次に、左側の数字
234 567
を抜き出します。

5、
そしてこれら1つ1つの数字に1を足し、これを9回繰り返します。
9の次は0で、0の次は1となります。
すると下記のようになります。

234 567
345 678
456 789
567 890
678 901
789 012
890 123
901 234
012 345
123 456


6、
次に、上記5、で得られた20個の数字行から0が含まれている数字行を
取り出します。
数字は3ケタですので、0が含まれる数字行は6行となります。

890 890
901 901
012 012


いかがでしょうか?これらの処理はC言語でできる物なのでしょうか?
宜しかったら教えて下さい。宜しくお願い致します。


他にも処理しなければならない情報は沢山あったのですが、それらは
表計算を工夫すれば何とか処理できる事が分りました。

表計算ソフトには、スクリプトやマクロがあるのですが(ロータススクリプト)
使いづらくまたマニュアルがないのでごく単純な事しかできませんでした。

スクリプトという事でJAVAスクリプトなのかと思い本を買ってみたところ
全くの別物。
ロータススクリプトの検索でプログラミングの書き方を探しましたが、
どうもノーツ?のスクリプトらしく、表計算のスクリプトとは記述が違いました。

ロータスからマニュアル本?(4500円)を取り寄せてもみましたが、
なんとスクリプト、マクロについて書かれているのはたったの1ページだけ
(スクリプトとマクロの両方が1ページに書かれている)
計ってみたら本の厚さは7cm。

No.8438

Re:宜しかったら教えて下さい
投稿者---物見遊山(2003/07/16 18:58:18)


>表計算ソフトの手動入力で今までやって来たのですが、
>処理する情報が膨れ上がってしまい、手動では対応できなくなって
>しまいました。
>
>そこでC言語の本を数冊ほど読んでみたのですが、
>データの処理に必要な方法を見つける事ができませんでした。

Cじゃないとダメなのですか?

>012 345/678/901全角 234 567

「全角」の部分は具体的にどんな文字列なのでしょう?
日本語のみ?それともアルファベットや数字も含むのでしょうか?

No.8443

Re:宜しかったら教えて下さい
投稿者---三浦忠(2003/07/16 19:43:40)
http://mi328.hp.infoseek.co.jp/


>Cじゃないとダメなのですか?

こんにちは、他の言語ならうまく処理できるでしょうか。
C言語は簡単な方で、他の言語は難しいと本で読んだので
C言語を選んだのですが。

>「全角」の部分は具体的にどんな文字列なのでしょう?
>日本語のみ?それともアルファベットや数字も含むのでしょうか?

全角のところは漢字です。


No.8444

Re:宜しかったら教えて下さい
投稿者---物見遊山(2003/07/16 19:54:44)


>C言語は簡単な方で、他の言語は難しいと本で読んだので
>C言語を選んだのですが。

Cはテキストの処理に向きません。
(できないわけではありませんが煩雑になります。)

>全角のところは漢字です。

じゃあ日本語に対応していて正規表現もでき
コンパイル不要のRubyが吉かと思います。
http://www.ruby-lang.org/ja/
お試しあれ。

No.8473

ありがとうございました
投稿者---三浦忠(2003/07/17 17:40:19)
http://mi328.hp.infoseek.co.jp/


きょうRubyの本を見に行きました。
しかし文字列の文字間に、区切りマークやスペースのない文章かから
任意の文字を取り出したり、

または区切りマークやスペースのない文章に、
区切りマークやスペースを挿入する方法などが書かれていなかったので、
諦めました。

使えそうな方法が書かれていたので、代わりにPerlの本を買いました。

VisualBasic6でも処理できる事が分りましたが、
生産中止との事でした。
(また現在のバージョンはWin98SEは対象外との事)


私が必要としている文字列処理の方法が、ちょっと特殊だったのでしょうか?
本当に困っていたので教えて頂きとても助かりました。ありがとうございました。


No.8479

Re:ありがとうございました
投稿者---物見遊山(2003/07/17 18:56:58)


>代わりにPerl

なんか悔しいので

>1、
>上記の文字列の中から、まず右から
>
>012 345 678 901
>
>を抜き出します。( ”/ ”と”全角”は必要ありません)

・・・の部分をRubyで書いてみた。
#!/usr/bin/ruby
require "kconv"

result = open("result.txt", "w")

while line = ARGF.gets
    element = Kconv.tosjis(line)
    result.puts element.gsub(/[^0-9\/ ]/s, "").gsub(/\//, " ")
end


10行に満たないで出来てしまうのだから素晴らしい。
#C言語に全然関係ありませんね。
#削除コードは1234です。>管理人さま

No.8456

Re:宜しかったら教えて下さい
投稿者---かずま(2003/07/16 21:52:44)


> いかがでしょうか?これらの処理はC言語でできる物なのでしょうか?

確かに、C は文字列処理が苦手ですが、手順が決まっているものは
たいてい処理できますよ。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

void step3(int n)
{
    do {
        int sum = 0;
        while (n != 0) sum += n % 10, n /= 10;
        n = sum;
    } while (n >= 10 && n != 11 && n != 22);
    printf("Step 3: %d\n", n);
}

void next(char *s) { for (; *s; s++) if (++*s > '9') *s = '0'; }
void zero(char *s) { strchr(s, '0') && printf("        %s\n", s); }

void step5(int n1, int n2)
{
    char b1[20], b2[20];  int i;

    printf("Step 5:\n"), sprintf(b1, "%d", n1), sprintf(b2, "%d", n2);
    for (i = 0; i < 10; i++)
        printf("        %s %s\n", b1, b2), next(b1), next(b2);
}

void step6(int n1, int n2)
{
    char b1[20], b2[20];  int i;

    printf("Step 6:\n"), sprintf(b1, "%d", n1), sprintf(b2, "%d", n2);
    for (i = 0; i < 10; i++)
        zero(b1), zero(b2), next(b1), next(b2);
}

void proc(const char *s)
{
    unsigned char c;  int sum = 0, n1, n2;

    printf("Step 1: ");
    while ((c = *s++) != 0 && c < 0x80)
        isdigit(c) ? (putchar(c), sum += c - '0') : putchar(' ');
    printf("\nStep 2: %d\n", sum);
    step3(sum);
    while ((c = *s) != 0 && !isdigit(c)) s++;
    if (sscanf(s, "%d%d", &n1, &n2) != 2) exit(1);
    printf("Step 4: %d %d\n", n1, n2);
    step5(n1, n2);
    step6(n1, n2);
}

int main(void)
{
    char *s = "012 345/678/901全角 234 567";

    printf("string: %s\n", s);
    proc(s);
    return 0;
}


No.8458

Re:宜しかったら教えて下さい
投稿者---かずま(2003/07/16 23:41:10)


> 確かに、C は文字列処理が苦手ですが、手順が決まっているものは
> たいてい処理できますよ。

step3, step5, step6 を関数にする必要性はありませんね。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

void next(char *s) { for (; *s; s++) if (++*s > '9') *s = '0'; }

void zero(char *s) { strchr(s, '0') && printf("        %s\n", s); }

void proc(const char *s)
{
    unsigned char c;  int i = 0, n1, n2;  char b1[20], b2[20];

    printf("Step 1: ");
    while ((c = *s++) != 0 && c < 0x80)
        isdigit(c) ? (putchar(c), i += c - '0') : putchar(' ');
    printf("\nStep 2: %d\n", i);
    do {
        int sum = 0;
        while (i != 0) sum += i % 10, i /= 10;
        i = sum;
    } while (i >= 10 && i != 11 && i != 22);
    printf("Step 3: %d\n", i);
    while ((c = *s) != 0 && !isdigit(c)) s++;
    if (sscanf(s, "%d%d", &n1, &n2) != 2) exit(1);
    printf("Step 4: %d %d\n", n1, n2);
    printf("Step 5:\n");
    sprintf(b1, "%d", n1), sprintf(b2, "%d", n2);
    for (i = 0; i < 10; i++)
        printf("        %s %s\n", b1, b2), next(b1), next(b2);
    printf("Step 6:\n");
    for (i = 0; i < 10; i++)
        zero(b1), zero(b2), next(b1), next(b2);
}

int main(void)
{
    char *s = "012 345/678/901全角 234 567";

    printf("string: %s\n", s);
    proc(s);
    return 0;
}


No.8463

Re:宜しかったら教えて下さい
投稿者---かずま(2003/07/17 11:24:41)


> step3, step5, step6 を関数にする必要性はありませんね。

全角の右の数字列が 0から始まっていると、それが消えるバグがあります。
次のように修正します。
>       while ((c = *s) != 0 && !isdigit(c)) s++;
>       if (sscanf(s, "%d%d", &n1, &n2) != 2) exit(1);
>       printf("Step 4: %d %d\n", n1, n2);

を
        if (sscanf(s, "%*[^0-9]%[0-9] %[0-9]", b1, b2) != 2) exit(1);
        printf("Step 4: %s %s\n", b1, b2);

に変更。

>       sprintf(b1, "%d", n1), sprintf(b2, "%d", n2);
を削除。

int i = 0, n1, n2; を int i = 0; に。


No.8478

ありがとうございました
投稿者---三浦忠(2003/07/17 18:43:18)
http://mi328.hp.infoseek.co.jp/


C言語でもできるんですね。

何をしたいのかを書いた方がいいかと思い、1つのブロックの
処理したい手順の全体を書きこんだのですが、
コードまで書きこんで頂きありがとうございました。

初心者なので、書きこんで頂いたコードを見ても、今のところは
ごく断片的なところしか理解できないのですが、
プリントしてC言語の本をみながら理解していきたいと思います。
ありがとうございました。