0

CSV形式を検出する割り当て用のプログラムをCで作成しようとしています。decimalcommadecimal。そして、ファイルが必要な形式であるかどうかに関する出力を提供します。stdinからのさまざまな入力やisdigitなどを使用してみましたが、成功しませんでした。私はメガ初心者で、これまでCプログラミングをほとんど行ったことがありません。regexcを使おうとしましたが、それを使用するための構文を理解できませんでした。

#include <ctype.h>
#include <stdio.h>
const char EOL = '\n';

int cbreak(void);
int check_dig(void);
int value =1;
char c;

int main()
{

    while((scanf("%c" ,&c)) !=EOF&& value !=0)
    check_dig();

    printf("\n%d\n",value);
}

int check_dig()
{
    if (c == EOL)
        scanf("%c", &c);
    if (c == isdigit)
        scanf("%c", &c);
    else if (c == ',')
        scanf("%c", &c);
    else value = 0;
}

ありがとうみんな私は今この段階にいますが、終了する方法として困惑しています。検証に応じて1または0のいずれかをprintfする必要があり、戻り値を使用して提案されたようにこれを実行したいと思います。

#include <ctype.h>
#include <stdio.h>

int check_digit(int);
int check_comma(int);
int skip_char(int);
int main()
{
    int c;

    while ((c = getchar()) !=EOF)
        if (check_digit(c))
            skip_char(c);
        else if (check_comma(c))
            skip_char(c);
        else return 0;
}

int check_digit(int c)
{   
    if (isdigit(c))
        return 1;
    else return 0;
}    

int check_comma(int c)
{
    if (c == ',')
        return 1;
    else return 0;
}

int skip_char(int c)
{
    c = getchar(); // will this skip 2 chars as i have a while loop that has c=getchar()??
    return c;
}
4

2 に答える 2

0

まず最初に、その膨大なグローバルリストを使用しないことをお勧めします。関数でパラメーターを使用し、関数から値を返します。

2番目isdigitはそのようには機能しません。パラメータを受け取り、trueまたはfalseを返します。isdigit

さらに、scanfではなくgetcharを使用します。

あなたのint check_dig()機能は少し奇妙です。関数内で文字を読み続けます。

私はおそらく次のようなことをします:

int valid_csv(char c)
{
    if (isdigit(c))
        return 1;
    /* etc. other checks */
    if all fails
    return 0;
}

int main(void)
{
    int c;

    /* read chars into c and call fun by something like */
    valid_svc(c);

    return 0;
}

編集:経験則として。関数は1つのことを実行し、1つのことだけを実行し、それをうまく実行する必要があります。関数の名前は、その機能を反映している必要があります。


Edit.2:

「charをスキップ」する必要はありません。新しいコードでは、1文字おきにスキップします。

すなわち:

ファイル:12,33,66,14

あなたのコードであなたは得るでしょう

  • c = getchar => c == 1
  • cは数字です
    • getchar => 2を読みます(そしてそれを検証することはありません)
  • c = getchar => c ==、
  • cはコンマです
    • getchar => 3を読みます(そしてそれを検証することはありません)
  • ..。

さらに遠く; 「関数は1つのことを実行する必要がある」と書いたことは知っていますが、そのリテラルではありません。つまり、あなたの新しいcheck_digitものは冗長です。isdigit直接使用してください。csvにフロートがある場合は、拡張するか、別のアプローチを使用する必要があります。

例で説明するために; ここに書くほうが簡単です:)

#include <ctype.h>
#include <stdio.h>

int valid_csv_chr(int);
int valid_csv(); /* guess naming could be better. */

int main(void)
{
    if (valid_csv())
        puts("1");
    else
        puts("0");

    return 0; /* Main should return 0 if there was no "crash" scenario etc.
     * You could also return i.e. 1 if the file is not validated as csv. 
     * Do not think of 1 and 0 as boolean true / false here. */
}

int valid_csv()
{
    int c;

    while((c = getchar()) !=EOF) {
        if (!valid_csv_chr(c)) {
            return 0;
        }
    }

    return 1;
}

int valid_csv_chr(int c)
{
    if (isdigit(c))
        return 1;
    if (c == ',')
        return 1;
    if (c == '\n')
        return 1;
        /* add checks for space etc. */
    return 0;
}

Edit.3:

コード構造は、言語自体と同じくらい多くを学ばなければならないものです。やって、書くことで学ぶことです。コードの再構造化が必要であることに気付く人は時々起こりますが、書く前に考え、最初に単純な構造を作り、それを拡張するなど、より避けられます。

とにかく; 練習、練習、練習。そして、これらのトピックを常に念頭に置いてください。

シンプルに「見える」ことができたとしても、そうではありません。多くの場合、本、チュートリアル、コースなどは、このトピックにほとんど焦点を当てていないと思います。それは、、、機能などのすべてであり、すべてを良い方法でつなぎ合わせる方法についてはほとんどありforませif

コードを分割することにはいくつかの利点があります。

  • それはそれをはるかに読みやすくします。
  • メンテナンスが容易になります。
  • バグやエラーは、多くの場合、大きな関数ではなく小さな関数を修正することで修正できます。
    • 場合によっては、バグのあるモンスター関数が含まれている数千行のコードを見たことがあります。微調整による修正はほぼ不可能であり、完全な書き直しは唯一の選択肢です。
  • 1つのタスクを実行し、それほど大きくない関数を最適化する方が簡単です。
  • 小さな関数を使用すると、より多くのシナリオをカバーするように拡張する方が簡単です。
    • たとえば、プログラムで言います。csv、タブ区切り、整列などをカバーする「データファイルの検証」に変更できます。

最後のポイントは、実際、私が書くときによく考える方法です。「将来、より多くのシナリオをカバーするようにコードを拡張したい場合に、簡単に実行できるように、このコードをどのように実装するのが最善でしょうか。」

私自身、K&RのANSI Cブック++で学んだことと組み合わせて、Cで書くときのベースとしてこれを使用します。たとえば、関数について書かれていることを参照してください。

また; コーディングスタイルに厳密であると、読みやすく、保守しやすくなります。私は主に上記のドキュメントで説明されているものを使用します。それは法則ではありませんが、それを意識することでコーディングの生活がとても簡単になります。

于 2012-04-13T01:04:09.963 に答える
0

特にCを初めて使用する場合は、この問題にregexcを使用することはお勧めしません。基本的な標準ライブラリ機能のいくつかを使用して問題を解決できるはずです。あなたは正しい一般的な軌道に乗っているようです。あなたは文字を読み、それらがどのクラスに適合するかを決定しています。有効な入力は数字とコンマ文字のみで構成されていることがわかっているので、これら2つ以外のものに遭遇した場合は、プログラムをすぐに終了できます。ここに役立つかもしれないいくつかのヒントがあります。

一度に1文字ずつ読んでいる場合は、getcharよりも使いやすいことがわかるかもしれませんscanf

また、isdigit関数です。言う代わりにif (c == isdigit)、あなたは言いたいですif (isdigit(c))

関数check_digはを返すように定義されていますが、関数にステートメントintがありません。return関数は値を返すように変更するmain必要があり、この値で何かを行う必要があります。一般的な経験則では、関数は正常に完了するとゼロを返し、エラーが発生するとゼロ以外を返します。あなたの場合、「成功」は「キャラクターが有効だった」を意味し、「エラー」は「キャラクターが無効だった」を意味する可能性があります。この変更を行うと、グローバル変数を削除できるはずですvalue。入力をパラメータとしてにc渡すと、グローバルを削除することもできます(内部でローカル変数になります)。check_digcmain()

数字を確認check_digする機能のみを使用し、別の文字を読み取る部分を削除することをお勧めします。を呼び出す前に、文字をスキップするかどうかを決定する必要があります。このようにして、「読み取り」コード、「スキップ」コード、および「チェック」コードを分離できます。これにより、プログラムの読み取りとデバッグが容易になります。check_dig

于 2012-04-13T01:07:58.810 に答える