C语言错误dinput error,C++基础--引用做函数参数

引用,简单粗暴的解释叫做别名,简单粗暴的例子就是,我是熊叫大雄,但是很多时候别人不叫我熊叫大雄,会叫我大雄,粤语地区朋友爱叫我阿雄,有人叫我雄,所以,熊叫大雄这个变量的值是我,雄、大雄、阿雄是熊叫大雄的别名,通过别名叫到的值还是我,晕了没?

这一篇主要讲引用做函数参数,引用还有其它内容,不过我觉得做函数参数比较常用且好理解一点,

1、创建引用

引用的创建形式有点类似指针,但是又有不同,一般这样创建引用:

int dNum1 = 1;

const int dNum2 = 1;

int &dNum11 = dNum1;  // OK

int &dNum111;         // ERROR

int &dNum1111 = 1;    // ERROR

int &dNum21 = dNum2;  // ERROR

上面这两句已经表明,引用的创建的时候就必须初始化的,也就是创建一个引用的时候不能够先说有个别名再说这个别名是谁的,必须是先有变量再有该变量引用,而且这个变量还不能是常量,否则也错误

在《C++ Primer Plus》一书有个说法是引用更接近const指针的伪装,例如声明引用的时候就有点像是这样:

int &dNum11 = dNum1;

==>

int * const dNum11 = &dNum1

所以,引用一旦声明之后就将与初始化的变量长伴一生,一生双存,一死双亡,一变俱变。

2、引用做函数参数

我觉得这个是比较能体现引用价值的地方之一。我们知道,在使用带参函数的时候,我们需要考虑的是参数的传入是否是变量本身,因为函数中有些操作可能是要对原变量进行改变的,之前C语言的做法是用指针来传递原变量地址,这样的好处是如果需要将改变传回或者改变原变量则不需要返回值,可以通过传入指针直接改变。那C++提供了引用的新特性,所以修改传入参数的时候就可以这样用了:

void suibianla(int &dInput)

{

dInput++;

}

int main(int argc, char* argv[])

{

int dNum1 = 1;

const int dNum2 = 1;

int &dNum11 = dNum1;

std::cout <

std::cout <

suibianla(dNum1);

std::cout <

std::cout <

system("pause");

return 0;

}

f5d30092f393f0c471a79a0b77c25aa4.png

这种方式跟指针做参数的方式有点类似,但是跟指针参数还是有区别的。

引用做参数的一些特点:

1、传递引用是传递原变量,不需要做变量拷贝,普通的变量做函数参数的时候会开辟内存拷贝数值,而传递引用则不需要开辟内存;

2、传递引用限制比传递普通函数严格,比如:

void suiBianLa(int dInput)

{

std::cout <

dInput++;

}

void aiZuoNiJiuZuoNi(int &dInput)

{

std::cout <

dInput++;

}

suiBianLa(dNum1 + 1);        // OK

aiZuoNiJiuZuoNi(dNum1 + 1);  // ERROR

aiZuoNiJiuZuoNi()的参数是引用,suiBianLa()的参数是普通变量,这个时候aiZuoNiJiuZuoNi()的使用是会报错的:

error C2664: “void aiZuoNiJiuZuoNi(int &)”: 无法将参数 1 从“int”转换为“int &”

3、如果既想用引用,又不想原始变量被改变,那么就用常量引用:

void aiZuoNi(const int &dInput)

{

std::cout <

dInput++;    // ERROR

}

因为是常量引用,所以不能对输入引用变量做改变的操作。

4、仅当使用常量引用的时候,如果输入参数与引用参数不匹配,才会生成临时变量,这种不匹配体现为:

(1)、实参的类型正确,但不是左值;

(2)、实参的类型不正确,但是可以转换为正确的类型。

有点不好理解,左值是啥?简单粗暴的说就是变量、数组元素、结构成员、引用和接触引用的指针等,非左值有字面常量、包含多项式的表达式等。

void aiZuoNi(const float &fInput)

{

std::cout <

}

long lNum = 1L;

float fNum = 1L;

aiZuoNi(lNum);        // lNum是long型,fInput是临时变量

aiZuoNi(fNum);        // fInput是fNum,没有临时变量

aiZuoNi(2.0);         // 2.0常量,有临时变量

aiZuoNi(fNum + 1);    // fNum + 1是表达式,有临时变量

同时注意到,aiZuoNi(fNum + 1)在非常量引用的时候是不行的,在常量引用下是可以的。

void aiZuoNi(const float &dInput)

{

std::cout <

std::cout <

}

long lNum = 1L;

float fNum = 1L;

aiZuoNi(lNum);

std::cout <

std::cout <

aiZuoNi(fNum);

std::cout <

std::cout <

aiZuoNi(2.0);

aiZuoNi(fNum + 1);

上述代码的运行结果是:

40e8dec9e39700f180f6894af6705a38.png

可以看到地址一样的只有aiZuoNi(fNum)调用的情况。

《C++ Primer Plus》给出的三个使用常量引用的理由是:

1、可以避免无意中修改数据的变成错误;

2、能够处理const和非const实参,否则只能使用非const数据,参见aiZuoNiJiuZuoNi(dNum1 + 1); // ERROR

3、使函数能够正确生成并使用临时变量

3、引用和指针的区别

声明方式不同,引用声明的时候必须初始化定义,指针可以先声明,再定义指向某个地址;

指针是需要分配内存的,指针本身占用内存来存储变量地址,引用不用,引用是原变量的别名,就还是原变量自己;

有多级指针,没见过多级引用;

sizeof(引用)得到的是所指向的变量(对象)的大小,而sizeof(指针)得到的是指针本身的大小,而不是指向对象的大小;

指针自增减是地址的增减。引用的自增减是变量值得自增减;

函数引用参数是类型安全,指针参数则不是(故常见指针参数需判断指针是否有效);

引用是从一而终,指针是见异思迁;

假如你不够快乐

也不要把眉头深锁

人生本来短暂

为什么 还要栽培苦涩

打开尘封的门窗

让阳光雨露洒遍每个角落

走向生命的原野

让风儿熨平前额

博大可以稀释忧愁

深色能够覆盖浅色

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C语言代码实现: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #define MAXSIZE 100 // 栈的最大容量 typedef char ElemType; // 栈存储的元素类型为字符 // 定义顺序栈结构体 typedef struct { ElemType data[MAXSIZE]; // 存储栈元素的数组 int top; // 栈顶指针 } SqStack; // 初始化顺序栈 void InitStack(SqStack *S) { S->top = -1; } // 判断栈是否为空 int StackEmpty(SqStack S) { return (S.top == -1); } // 判断栈是否已满 int StackFull(SqStack S) { return (S.top == MAXSIZE - 1); } // 进栈 int Push(SqStack *S, ElemType e) { if (StackFull(*S)) { // 栈已满,无法进栈 return 0; } S->top++; S->data[S->top] = e; return 1; } // 出栈 int Pop(SqStack *S, ElemType *e) { if (StackEmpty(*S)) { // 栈已空,无法出栈 return 0; } *e = S->data[S->top]; S->top--; return 1; } // 获取栈顶元素 int GetTop(SqStack S, ElemType *e) { if (StackEmpty(S)) { // 栈已空,无法获取栈顶元素 return 0; } *e = S.data[S.top]; return 1; } // 比较运算符优先级 int Precede(ElemType x, ElemType y) { int i, j; char pri[7][7] = { // 运算符优先级静态表 {'>', '>', '<', '<', '<', '>', '>'}, {'>', '>', '<', '<', '<', '>', '>'}, {'>', '>', '>', '>', '<', '>', '>'}, {'>', '>', '>', '>', '<', '>', '>'}, {'<', '<', '<', '<', '<', '=', ' '}, {'>', '>', '>', '>', ' ', '>', '>'}, {'<', '<', '<', '<', '<', ' ', '='} }; switch (x) { case '+': i = 0; break; case '-': i = 1; break; case '*': i = 2; break; case '/': i = 3; break; case '(': i = 4; break; case ')': i = 5; break; case '=': i = 6; break; default: i = 7; break; } switch (y) { case '+': j = 0; break; case '-': j = 1; break; case '*': j = 2; break; case '/': j = 3; break; case '(': j = 4; break; case ')': j = 5; break; case '=': j = 6; break; default: j = 7; break; } return pri[i][j]; } // 计算两个操作数的结果 double Operate(double a, ElemType theta, double b) { double result = 0.0; switch (theta) { case '+': result = a + b; break; case '-': result = a - b; break; case '*': result = a * b; break; case '/': result = a / b; break; } return result; } // 计算中缀表达式的值 double EvaluateExpression(char *exp) { SqStack OPTR, OPND; ElemType c, x, theta; double a, b, d, e; InitStack(&OPTR); InitStack(&OPND); Push(&OPTR, '='); // 表达式以'='结束 c = *exp++; while (c != '=' || GetTop(OPTR, &x) != '=') { if (c >= '0' && c <= '9') { // c是操作数,进栈OPND d = c - '0'; while (*exp >= '0' && *exp <= '9') { // 取得操作数的完整数值 d = d * 10 + (*exp - '0'); exp++; } if (*exp == '.') { // 处理小数部分 exp++; e = 0.1; while (*exp >= '0' && *exp <= '9') { d += (*exp - '0') * e; e *= 0.1; exp++; } } Push(&OPND, d); // 操作数进栈 c = *exp++; // 处理下一个字符 } else { // c是运算符 switch (Precede(x, c)) { case '<': // 栈顶运算符优先级低,进栈OPTR Push(&OPTR, c); c = *exp++; break; case '=': // 脱括号并接收下一字符 Pop(&OPTR, &x); c = *exp++; break; case '>': // 退栈并将运算结果进栈OPND Pop(&OPTR, &theta); Pop(&OPND, &b); Pop(&OPND, &a); Push(&OPND, Operate(a, theta, b)); break; } } } return GetTop(OPND, &a) ? a : 0.0; // 返回最终结果 } int main() { char exp[41]; printf("Please input an infix expression (with '=' at the end):\n"); scanf("%s", exp); double result = EvaluateExpression(exp); if (result == 0.0) { printf("ERROR\n"); } else { printf("The result is %.2f\n", result); } return 0; } ``` 代码中使用了两个顺序栈,一个用于存储运算符,一个用于存储操作数。每次读入一个字符,若为操作数则取完整数值并进栈OPND,若为运算符则与栈顶运算符比较优先级。若栈顶运算符优先级低,则进栈OPTR;若相等,则脱括号并读入下一个字符;若栈顶运算符优先级高,则退栈并将运算结果进栈OPND。最终结果存在OPND栈中,返回栈顶元素即可。 需要注意的是,该代码实现假设所有操作数均为正数,且输入的表达式不超过40个字符。对于负数、小数、超长表达式等情况,还需要进行相应的修改和处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值