2016-03-26 22 views
0

static const vs #defineまたは#defining constants in C++ではありません。Cで以前に定義された定数を使用して静的constを定義する方法は?

私がCで多くのプログラミングをしたとき、ANSI Cはまったく新しいものでした。 #defineを使用して定数を定義していました。私はこれがもはやベストプラクティスではないことを認識しました(https://codereview.stackexchange.com/questions/123848/verifying-e-mail-address-in-c/123856#123856)。しかし、私はexampe私は私はむしろの#defineより静的定数を使用しようとしている(以下)プログラムを有する

#define EMAIL_CHAR_ARRAY_SIZE 40 
#define GOOD_EMAIL_ADDRESS 1 
#define BAD_EMAIL_ADDRESS 0 
#define MIMIMUM_USER_NAME_LENGTH 1 
#define AT_SIGN_LENGTH 1 
#define DOT_LENGTH 1 
#define MINIMUM_DOMAIN_LENGTH 1 
#define MINIMUM_ROOT_DOMAIN_LENGTH 2 
#define MINIUMUM_EMAIL_LENGTH MIMIMUM_USER_NAME_LENGTH + AT_SIGN_LENGTH + MINIMUM_DOMAIN_LENGTH + MINIMUM_ROOT_DOMAIN_LENGTH 

で、現在の定数を定義するために、以前の定数を使用することができます。#defineを使用

前の定数を使って静的constを使用しようとすると、定数MINIUMUM_EMAIL_LENGTHはコンパイルされません。以前に定義された定数をstatic const TYPE宣言で使用する方法はありますか?

const_testemail.c:12:5: error: initializer element is not constant 
    static const int MINIUMUM_EMAIL_LENGTH = (MIMIMUM_USER_NAME_LENGTH + AT_SIGN_LENGTH + MINIMUM_DOMAIN_LENGTH + MINIMUM_ROOT_DOMAIN_LENGTH); 


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

static const int EMAIL_CHAR_ARRAY_SIZE = 40; 
static const int GOOD_EMAIL_ADDRESS = 1; 
static const int BAD_EMAIL_ADDRESS = 0; 
static const int MIMIMUM_USER_NAME_LENGTH = 1; 
static const int AT_SIGN_LENGTH = 1; 
static const int DOT_LENGTH = 1; 
static const int MINIMUM_DOMAIN_LENGTH = 1; 
static const int MINIMUM_ROOT_DOMAIN_LENGTH = 2; 
/* Doesn't compile 
* static const int MINIUMUM_EMAIL_LENGTH = MIMIMUM_USER_NAME_LENGTH + AT_SIGN_LENGTH + MINIMUM_DOMAIN_LENGTH + MINIMUM_ROOT_DOMAIN_LENGTH; 
* */ 

#define MINIUMUM_EMAIL_LENGTH (MIMIMUM_USER_NAME_LENGTH + AT_SIGN_LENGTH + MINIMUM_DOMAIN_LENGTH + MINIMUM_ROOT_DOMAIN_LENGTH) 

int isEmailAddressProper(const char EmailAddress[EMAIL_CHAR_ARRAY_SIZE]) 
{ 
    int  EmailAddressIsGood = GOOD_EMAIL_ADDRESS; 
    int  LengthOfEmailAddress; 
    char *AtSignLocation, *pos2; 
    int  rootDomainLength; 

    LengthOfEmailAddress = strlen(EmailAddress); 
    if (LengthOfEmailAddress < MINIUMUM_EMAIL_LENGTH) 
    { 
     printf("The length of the email address is less than the minimum lenght %d\n", MINIUMUM_EMAIL_LENGTH); 
     EmailAddressIsGood = BAD_EMAIL_ADDRESS; 
    } 

    AtSignLocation = strchr(EmailAddress, '@'); /* get the first instance of @ */ 
    if (!AtSignLocation) 
    { 
     printf("There is no @ in the email address\n"); 
     EmailAddressIsGood = BAD_EMAIL_ADDRESS; 
     return EmailAddressIsGood; 
    } 

    if (AtSignLocation == EmailAddress) { /* Is @ the first character? */ 
     printf("There is no user name in the email address, @ is the first character\n"); 
     EmailAddressIsGood = BAD_EMAIL_ADDRESS; 
    } 

    pos2 = strrchr(EmailAddress, '@'); /* find any other @ */ 
    if ((pos2) && (AtSignLocation != pos2)) { 
     printf("There is more than 1 @ in the email address\n"); 
     EmailAddressIsGood = BAD_EMAIL_ADDRESS; 
    } 

    pos2 = strrchr(EmailAddress, '.'); /* get the last instance of '.' */ 
    if (AtSignLocation > pos2) /* is . before @ ? */ 
    {   printf("There is no root domain in the email address\n"); 
     EmailAddressIsGood = BAD_EMAIL_ADDRESS; 
    } 

    pos2++; 
    rootDomainLength = LengthOfEmailAddress - ((int)(pos2 - EmailAddress)); 
    /* if root domain less than length 2 */ 
    if (rootDomainLength < MINIMUM_ROOT_DOMAIN_LENGTH) 
    { 
     printf("The root domain length (%d) is less than the minimum length required (%d) in the email address\n", rootDomainLength, MINIMUM_ROOT_DOMAIN_LENGTH); 
     EmailAddressIsGood = BAD_EMAIL_ADDRESS; 
    } 

    return EmailAddressIsGood; 
} 

void GetAndValidateEmailAddress(char EmailAddress[EMAIL_CHAR_ARRAY_SIZE]) 
{ 
    int EmailAddressIsGood = BAD_EMAIL_ADDRESS; 
    char TempEmail[EMAIL_CHAR_ARRAY_SIZE]; 

    while (!EmailAddressIsGood) 
    { 
     scanf("%39s", TempEmail); 
     EmailAddressIsGood = isEmailAddressProper(TempEmail); 
     if (!EmailAddressIsGood) { 
      printf("The email address is not in the proper format, please re-enter the email address\n"); 
     } 
    } 

    strcpy(EmailAddress, TempEmail); 
} 

main() 
{ 
    char EmailAddress[EMAIL_CHAR_ARRAY_SIZE]; 

    printf("Please enter the email address\n"); 
    GetAndValidateEmailAddress(EmailAddress); 
    printf("The email address you entered is %s\n", EmailAddress); 
} 
+0

@Olafあなたの答えは、C言語を使って定数を作成する方法がないということです。これは非常に悪いプログラミングの練習になります。 – pacmaninbw

+0

いいえ、私はこれを述べませんでした。これは、マクロが使用されるためです。 Cには定数があることに注意してください。 '1'は' int'型の定数、 '0.3f'は' float'定数などです。問題は**ユーザ定義の型を持つ**記号**の定数です。マクロを使用します。異なる翻訳フェーズですが、それはC言語で動作する方法です。ローマにいる場合、ローマ字のように動作します。 – Olaf

+0

コンパイラの仕組みはよく分かりませんが、コメントが付いたマクロにタイプミスがあります。それを修正して、やり直してください。あなたは純粋にCですか? –

答えて

0

Cは(常にタイプintのある)列挙-定数以外の記号定数を有していません。 #defineはマクロであり、プロセッサの一部です。これは、実際のC言語のコンパイルの前のテキスト置換です。

const修飾された変数は、意味的にはまだ変数です。修飾子はプログラマによる保証であり、値を変更しません。コンパイラはこの保証に依存することがあります。契約を破ると、未定義の動作が呼び出されますが、必ずしも実行時環境によって強制されるわけではありません。

ファイルレベルの静的な初期化子と配列インデックスには、という定数式が必要です。したがって、エラーです。つまり、定数式は、コンパイル時に一定の値を生成する必要があるため、変数を使用することはできません。

注意関数内の配列パラメータにも同様の問題があります。しかし、ここでは可変長配列を使うことができます。ただし、空の長さ([])を使用するか、長さを前のパラメータとして明示的に渡すことができます。グローバル変数は動作しません:

int isEmailAddressProper(size_t len, const char EmailAddress[len]) 

C++は似た構文/文法と異なる言語であり、さらには同じ文法のためにかなり異なる意味。言語の知識を他の言語に適用することはできません。

+0

静的const intはまだ変数なので、定数を定義する際には使用できません。これはあなたが言っていることです。エラーメッセージが追加されました。警告はありません。 – pacmaninbw