2012-11-29 99 views
-1

的代碼,我在這裏字符串轉換爲類複雜......拒絕訪問錯誤

void StrtoComplex(char *temp) 
    { 
     int i; 

     for(i = 0; i < strlen(temp); i++) 
     { 
      if(temp[i] == 'j' || temp[i] == 'i') 
       break; 
     } 

     real = atof(temp);//takes till the last valid char so after + or whitespace it ignores 
     imag = atof(temp + i + 1); 

     sprintf(complexStr, "%f +j%f", real, imag); 
    } 

它編譯但在運行它執行的所有語句(用正確的價值觀.... complexStr也有正確的字符串。 ..)但隨後又回到sprintf的聲明,並表示拒絕訪問

確定這裏是代碼的其餘部分....

#include <iostream> 
#include <conio.h> 
#include <string.h> 

#include <cstdlib> 
#include <cctype> 
#include <cstring> 

//Most string operations require the std namespace 
using namespace std; 


//namespace helps divide global access into subaccess blocks providing data encapsulation 
//If required to use any defined within a namespace use scope resolution 
namespace Complex 
{ 
    /*This is the Complex class which is asscociated with its corresponding string holding 
    the complex representation 
    DATA MEMBERS: 
    real --------- real part of the complex number 
    imag --------- imaginary part of the complex number 
    complexstr --- string stream which holds the complex representation 
    MEMBER FUNCTIONS 
    */ 
    class complex 
    { 
     double real; 
     double imag; 
     char complexStr[50]; 

    public: 
     complex(double re = 0, double im = 0) 
     { 
      real = re; 
      imag = im; 
      sprintf(complexStr, "%f +j%f",real,imag); 
     } 

     complex(complex &t) 
     { 
      real = t.real; 
      imag = t.imag; 
     } 

     void StrtoComplex(char *temp) 
     { 
      int i; 

      for(i = 0; i < strlen(temp); i++) 
      { 
       if(temp[i] == 'j' || temp[i] == 'i') 
        break; 
      } 

      real = atof(temp);//takes till the last valid char so after + or whitespace it ignores 
      imag = atof(temp + i + 1); 

      sprintf(complexStr, "%f +j%f", real, imag); 
     } 

     friend complex operator+(complex &a, complex &b); 
     friend complex operator-(complex &a, complex &b); 
     friend complex operator-(complex &a); 
     friend complex operator*(complex &a, complex &b); 
     friend complex operator/(complex &a, complex &b); 
     friend ostream &operator<<(ostream &s, complex &t); 
     friend istream &operator>>(istream &s, complex &t); 
    }; 

    //overloading + to add complex numbers 
    complex operator +(complex &a, complex &b) 
    { 
     complex t; 
     t.real = a.real + b.real; 
     t.imag = a.imag + b.imag; 
     sprintf(t.complexStr, "%f +j%f", t.real, t.imag); 
     return(t); 
    } 
    //overaloading - to subtract 2 complex no's 
    complex operator -(complex &a, complex &b) 
    { 
     complex t; 
     t.real = a.real - b.real; 
     t.imag = a.imag - b.imag; 
     sprintf(t.complexStr, "%f +j%f", t.real, t.imag); 
     return(t); 
    } 

    //overloading unary - 
    complex operator -(complex &a) 
    { 
     complex t(-a.real, -a.imag); 
     sprintf(t.complexStr, "%f +j%f", t.real, t.imag); 
     return(t); 
    } 

    //overloading * to multiply 2 complex no's 
    complex operator *(complex &a, complex &b) 
    { 
     complex t; 
     t.real = (a.real*b.real) - (a.imag*b.imag); 
     t.imag = (a.real*b.imag) + (a.imag*b.real); 
     sprintf(t.complexStr, "%f +j%f", t.real, t.imag); 
     return(t); 
    } 
    //overloading/to divide 2 complex no's 
    complex operator /(complex &a, complex &b) 
    { 
     complex t; 
     t.real = ((a.real*b.real) + (a.imag*b.imag))/(b.real*b.real + b.imag*b.imag); 
     t.imag = ((a.real*b.imag) - (a.imag*b.real))/(b.real*b.real + b.imag*b.imag); 
     sprintf(t.complexStr, "%f +j%f", t.real, t.imag); 
     return(t); 
    } 

    ostream &operator<<(ostream &s, complex &t) 
    { 
     s<<t.complexStr; 
     return s; 
    } 

    istream &operator>>(istream &s, complex &t) 
    { 
     char *temp; 

     s>>temp; 
     t.StrtoComplex(temp); 
     return s; 
    } 
} 

namespace Discrete 
{ 
    using Complex::complex; 
    class signal 
    { 
     complex *sig_Data; 

     int range_start, range_end, zero_pt; 

    public: 
     signal() 
     { 
      sig_Data = NULL; 
      range_start = range_end = zero_pt = 0; 
     } 

     signal(complex i) 
     { 
      sig_Data = new complex(i); 
      range_start = range_end = zero_pt = 0; 
     } 

     signal(int r_start, int r_end, int z_pt) 
     { 
      range_start = r_start; 
      range_end = r_end; 
      zero_pt = z_pt; 
      int arr_ind = r_end - r_start; 

      sig_Data = new complex [arr_ind]; 
     } 

     signal(signal &s) 
     { 
      sig_Data = s.sig_Data; 
      range_start = s.range_start; 
      range_end = s.range_end; 
      zero_pt = s.zero_pt; 
     } 

     void StrtoSig(char *temp) 
     { 
      int arr_ind = 0; 
      char *tok; 

      if(!*temp) return; 

      tok = temp; 
      zero_pt = 0; 
      // 
      int flag; 

      for(int i = 0; i < (flag = strlen(temp)); i++) 
      { 
       tok++; 
       if(*tok == '^') zero_pt = arr_ind; 
       if(*tok == ',') arr_ind++; 
      } 
      range_start = 0 - zero_pt; 
      range_end = arr_ind - zero_pt; 

      sig_Data = new complex [arr_ind]; 
      tok = temp+1; 
      for(int i = 0; i <= arr_ind; i++) 
      { 
       if(*tok == '^') tok++; 
       sig_Data[i].StrtoComplex(tok); 
       while(*tok != ',' || *tok != '}'|| *tok != '\0') tok++; 
      } 
     } 

     complex operator[](int i) 
     { 
      if(i >= range_start && i <= range_end) return sig_Data[zero_pt+i]; 
      else return complex(0); 
     } 

     void timeScale(float t) 
     { 
      if(t!=0) 
      { 
       int range = abs((int)((range_end - range_start)/t)); 
       int flag = 0; 
       complex *sig=new complex[range]; 
       for(int i = 0; i < range; i++) 
       { 
        if(((long)(range_start + i)/t) == (range_start + i)/t) 
         sig[flag++] = sig_Data[i]; 
       } 
       sig_Data = sig; 
       range_start = (range_start)/t; 
       range_end = (range_end)/t; 
       zero_pt = (zero_pt)/t; 
      } 
      else 
      { 
       cout<<"time scaling not possible. Scaling factor is invalid."; 
       return; 
      } 
     } 

     //time shifting function 
     void timeShift(int i) 
     { 
      if(i != 0) 
      { 
       range_start -= i; 
       range_end -= i; 
       zero_pt += i; 
      } 
      return; 
     } 

     friend signal operator+(signal &a, signal &b); 
     friend signal operator-(signal &a, signal &b); 
     friend signal operator-(signal &a); 
     friend signal operator*(signal &a, signal &b); 

     friend ostream &operator<<(ostream &s, signal &t); 
     friend istream &operator>>(istream &s, signal &t); 
    }; 

    //Overloading + operator 
    signal operator+(signal &a, signal &b) 
    { 
     int r_start = min(a.range_start, b.range_start); 
     int r_end = max(a.range_end, b.range_end); 
     int z_pt = max(a.zero_pt, b.zero_pt); 
     signal temp(r_start, r_end, z_pt); 
     for(int i = r_start; i < r_end; i++) 
     { 
      temp[i] = a[i] + b[i]; 
     } 
     return temp; 
    } 

    //Overloading - operator 
    signal operator-(signal &a, signal &b) 
    { 
     int r_start = min(a.range_start, b.range_start); 
     int r_end = max(a.range_end, b.range_end); 
     int z_pt = max(a.zero_pt, b.zero_pt); 
     signal temp(r_start, r_end, z_pt); 
     for(int i = r_start; i < r_end; i++) 
     { 
      temp[i] = a[i] - b[i]; 
     } 
     return temp; 
    } 

    //Overloading unary- operator 
    signal operator-(signal &a) 
    { 
     signal temp = a; 
     for(int i = a.range_start; i < a.range_end; i++) 
     { 
      temp[i] = -a[i]; 
     } 
     return temp; 
    } 

    //Overloading * operator 
    signal operator*(signal &a, signal &b) 
    { 
     int r_start = min(a.range_start, b.range_start); 
     int r_end = max(a.range_end, b.range_end); 
     int z_pt = max(a.zero_pt, b.zero_pt); 
     signal temp(r_start, r_end, z_pt); 
     for(int i = r_start; i < r_end; i++) 
     { 
      temp[i] = a[i] * b[i]; 
     } 
     return temp; 
    } 

    ostream &operator<<(ostream &s, signal &t) 
    { 
     int arr_ind = t.range_end - t.range_start; 
     s<<"{"; 
     for(int i = 0; i < arr_ind; i++) 
     { 
      if(i == t.zero_pt) 
       s<<" ^"<<t[i]; 
      else 
       s<<" "<<t[i]; 
     } 
     s<<"}"; 
     return s; 
    } 

    istream &operator>>(istream &s, signal &t) 
    { 
     char *ip; 
     s>>ip; 
     t.StrtoSig(ip); 
     return s; 
    } 
} 

namespace Parser 
{ 
    using Discrete::signal; 
    enum types { DELIMITER = 1, VARIABLE, NUMBER, SIGNAL }; 

    const int NUMVARS = 26; // No. of variable names .....the alphabet 
    class parser 
    { 
     char *exp_ptr; //points to the expression 
     char token[80]; //holds current token 
     char tok_type; //holds token's type 
     signal vars[NUMVARS]; //holds variable's values 

     void eval_exp1(signal &result); 
     void eval_exp2(signal &result); 
     void eval_exp3(signal &result); 
     void eval_exp4(signal &result); 
     void eval_exp5(signal &result); 
     void eval_exp6(signal &result); 
     void eval_time1(signal &result); 
     void eval_time2(signal &result); 

     void atom(signal &resutl); 
     void get_token(), putback(); 
     void serror(int error); 
     signal find_var(char *s); 
     int isdelim(char c); 

    public: 
     parser(); 
     signal eval_exp(char *exp); 
    }; 

    //Parser constructor 
    parser::parser() 
    { 
     int i; 

     exp_ptr = NULL; 
     for(i = 0; i < NUMVARS; i++) vars[i] = (signal) 0; 
    } 

    //Parser entry point 
    signal parser::eval_exp(char *exp) 
    { 
     signal result; 

     exp_ptr = exp; 

     get_token(); 
     if(!*token) 
     { 
      serror(2);//no expression present 
      return (signal) 0; 
     } 

     eval_exp1(result); 
     if(*token) serror(0); //last token must be null 
     return result; 
    } 

    //Process an assignment 
    void parser::eval_exp1(signal &result) 
    { 
     int slot; 
     char ttok_type; 
     char temp_token[80]; 

     if(tok_type == VARIABLE) 
     { 
      //save old token 
      strcpy(temp_token, token); 
      ttok_type = tok_type; 
      //compute the index of the variable 
      slot = toupper(*token) - 'A'; 

      get_token(); 
      if(*token != '=') 
      { 
       putback();//return curent token 
       //restore old token - not assignment 
       strcpy(token, temp_token); 
       tok_type = ttok_type; 
      } 

      else 
      { 
       get_token(); //get the next part of the exp 
       eval_exp2(result); 
       vars[slot] = result; 
       return; 
      } 
     } 

     eval_exp2(result); 
    } 

    //Add or subtract two terms 
    void parser::eval_exp2(signal &result) 
    { 
     register char op; 
     signal temp; 

     eval_exp3(result); 
     while((op = *token) == '+' || op == '-') 
     { 
      get_token(); 
      eval_exp3(temp); 
      switch (op) 
      { 
      case '-': 
       result = result - temp; 
       break; 
      case '+': 
       result = result + temp; 
       break; 
      } 
     } 
    } 

    //Multiply or divide two factors 
    void parser::eval_exp3(signal &result) 
    { 
     register char op; 
     signal temp; 

     eval_exp4(result); 
     while((op = *token) == '*' || op == '&') 
     { 
      get_token(); 
      eval_exp4(temp); 
      switch(op) 
      { 
      case '*': 
       result = result * temp; 
       break; 
      case '&': 
       //Convolution if possible 
       break; 
      } 
     } 
    } 


    //Evaluate a unary + or - 
    void parser::eval_exp4(signal &result) 
    { 
     register char op; 

     op = 0; 
     if((tok_type == DELIMITER) && *token == '+' || *token == '-') 
     { 
      op = *token; 
      get_token(); 
     } 

     eval_exp5(result); 
     if(op == '-') result = -result; 
    } 

    //Process a parenthesized expression 
    void parser::eval_exp5(signal &result) 
    { 
     if(*token == '(') 
     { 
      get_token(); 
      eval_exp2(result); 
      if(*token != ')') 
       serror(1); 
      get_token(); 
     } 
     else atom(result); 
    } 

    //Get the value of a number or a variable 
    void parser::atom(signal &result) 
    { 
     switch(tok_type) 
     { 
     case VARIABLE: 
      result = find_var(token); 
      eval_time1(result); 
      get_token(); 
      return; 
     case NUMBER: 
      result = (signal)atof(token); 
      get_token(); 
      return; 
     case SIGNAL: 
      result.StrtoSig(token); 
      get_token(); 
      return; 
     default: 
      serror(0); 
     } 
    } 

    //Time scaling 
    void parser::eval_time1(signal &result) 
    { 
     int i = 0; 
     while(token[i] != '[' || token[i] != 0) i++; 
     if(token[i] == '[') 
     { 
      eval_time2(result); 
      i++; 
      float x; 
      if((x = atof(&token[i])) != 0) 
       result.timeScale(x);//atoi takes care of the + and - if existing in the string 
     } 
    } 

    //Time shifting 
    void parser::eval_time2(signal &result) 
    { 
     int i = 0; 
     while(token[i] != '[' || token[i] != 0) i++; 
     if(token[i] == '[') 
     { 
      i++; 
      while(token[i] != '+' || token[i] != '-' || ']') i++; 
      result.timeShift(atoi(&token[i+1]));//atoi takes care of the + and - existing in the string 
     } 
    } 

    //Return a token to the input stream 
    void parser::putback() 
    { 
     char *t; 

     t = token; 
     for(; *t; t++) exp_ptr--; 
    } 

    //Display a syntax error 
    void parser::serror(int error) 
    { 
     static char *e[] = { 
      "Syntax Error", 
      "Unbalanced Parenthesis", 
      "No expression present" 
     }; 
     cout<<e[error]<<endl; 
    } 

    //Obtain next token 
    void parser::get_token() 
    { 
     register char *temp; 

     tok_type = 0; 
     temp = token; 
     *temp = '\0'; 

     if(!*exp_ptr) return; //at end of expression 

     while(isspace(*exp_ptr)) ++exp_ptr; //skip over the white spaces 

     if(strchr("+-*&=()", *exp_ptr)) 
     { 
      tok_type = DELIMITER; 
      //advance to the next char 
      *temp++ = *exp_ptr++; 
     } 

     else if(isalpha(*exp_ptr)) 
     { 
      while(!isdelim(*exp_ptr)) 
      { 
       *temp++ = *exp_ptr++; 
       if(*exp_ptr == '[') 
       { 
        do 
        { 
         *temp++ = *exp_ptr++; 
        } while(*exp_ptr != ']'); 
       } 
      } 
      tok_type = VARIABLE; 
     } 

     else if(isdigit(*exp_ptr)) 
     { 
      while(!isdelim(*exp_ptr)) *temp++ = *exp_ptr++; 
      tok_type = NUMBER; 
     } 

     else if(*exp_ptr == '{') 
     { 
      do 
      { 
       *temp++ = *exp_ptr++; 
      } while(*exp_ptr != '}'); 
      tok_type = SIGNAL; 
     } 
     *temp = '\0'; 
    } 

    //Return true if c is delimiter 
    int parser::isdelim(char c) 
    { 
     if(strchr("+-*&=()", c) || c == 9 || c == '\r' || c == 0) 
      return 1; 
     return 0; 
    } 

    //return value of a variable 
    signal parser::find_var(char *s) 
    { 
     if(!isalpha(*s)) 
     { 
      serror(1); 
      return signal(0); 
     } 
     return vars[toupper(*token) - 'A']; 
    } 
} 


void main() 
{ 
    using Parser::parser; 

    parser eQuation; 
    char expression[100]; 

    cout<<"Basic Signal Arithmetic Calculator"<<endl; 
    cout<<"Use this program to perform basic addition, subtraction and multiplication of signals with time scaling and time shifting"<<endl; 
    cout<<endl<<"Instructions:"<<endl<<"1. Use assignment operation to give values to variables. Enter signals within '{' and '}' and elements seperaed by ','"; 
    cout<<endl<<"\tExample: x = {12+i6, 13+i5}"; 
    cout<<endl<<"2. Use '^' before an element to indicate zero position. By default the 1st element is assumed to be at zero position"; 
    cout<<endl<<"3. You can include time scaling and shifting within the equation by using the '[' and ']'"; 
    cout<<endl<<"\tExample: x[2n+3] = y + z[n+5] +{2+i3, ^4+i1}"; 
    cout<<endl<<"4. Type 'exit' to exit the program"; 
    cout<<endl<<"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"<<endl; 

    do 
    { 
     cout<<"Enter your equation:"<<endl; 
     cin.get(expression, 100); 

     if(!strcmp(expression, "exit")) 
      break; 

     cout<<endl<<"ans: "; 
     cout<<endl<<eQuation.eval_exp(expression); 
    }while(1); 


    getch(); 
} 

請幫助

+3

很確定您的訪問權限與您向我們展示的代碼無關。 – ScoPi

+1

你發給這個功能的是什麼? – Maroun

+2

什麼是'complexStr'? –

回答

1

我認爲這個問題是在功能StrToSig()最後代碼:

while(*tok != ',' || *tok != '}'|| *tok != '\0') tok++; 

當然,*tok總是是不同的其中之一(事實上,至少兩個)。這將永遠運行,最終會讓tok進入無法訪問的內存。只要將其修正爲:

while(*tok != ',' && *tok != '}'&& *tok != '\0') tok++; 

然後你有第二個問題:爲complex拷貝構造函數是不好的,因爲它不會複製complexStr,所以你會與未初始化字符串有結束。

使用const引用而不是值也會改善您的程序,但這不在您的問題的範圍內。

+0

這有助於解決此問題。非常感謝。 – PSK

+0

@PSK不客氣 – Gorpik

1

你的問題是在istream &operator>>(istream &s, complex &t)

您創建了一個char*,指向無處,然後要求cin將數據彈入其中。遺憾的是cin不會爲您分配內存,因此您會將垃圾傳入您的StrtoComplex函數,導致其崩潰。

您真正想要做的是(將代碼更改最小化)將輸入輸入std::string,然後將.c_str()從中輸入並傳遞到解析器。有更多的慣用方法使用std::string始終與例如std::find一起使用,但這應該讓你更遠。

istream &operator>>(istream &s, complex &t) 
{ 
    std::string temp; 

    std::getline(s, temp); 
    t.StrtoComplex(temp.c_str()); 
    return s; 
} 

最後請注意,我會建議使用的std::string代替char[50]您complexStr表示,它會確保有足夠的總內存爲您的需求。

最後,我想說「即使你知道你不會溢出也不要使用sprintf」,因爲某些時候有人會對你的代碼或輸入進行無害的改變,並溢出緩衝區。 總是使用snprintf(或_snprintf如果您的編譯器已決定不支持C99)。

+0

這個建議非常讚賞,但它似乎並沒有解決這個問題。從函數'StrtoSig'調用此函數'StrtoComplex'時出現此錯誤 – PSK