The message says that you try to assign to an expression which is not an lvalue. For built-in types, you can only assign to lvalues (that’s where the name comes from: lvalue = value that can be on the left hand side of the assignment operator, while rvalue = value that must be on the right hand side of the assignment operator).
So what is an lvalue or an rvalue? Consider the following code:
int a;
a = 3;
In this assignment a is an lvalue (if it weren’t, the compiler would complain). That is, the expression a refers to an object which can be modified. On the other hand, 3 is an rvalue, that is, basically a value. Of course you cannot assign to 3; the compiler would complain about the statement 3=a; with exactly the same message you got in your code.
So as a first approximation, an lvalue designates an object, while an rvalue designates a value. Note that this is also true for assignment of the form
a = b;
where b also is a variable. What happens here is the so-called lvalue to rvalue conversion: What is assigned is not the object b, but its current value.
Now consider the following case:
int f();
f() = 3;
Here you might argue that the function f does return an object (if you use some user-defined type, you even can see its construction/destruction). But the compiler still complains with the message you got. Why?
Well, even if you consider f to return an object, it is a temporary object which will go away immediately. So it does not make much sense to assign a value because you cannot do anything with it anyway afterwards.
Therefore here’s the second rule:
Whenever there’s an expression which produces a temporary object, C++ defines that expression as rvalue.
And now we come to the definition of MyVector::at() which you did not show, but which, according to the error message, probably looks similar to this:
template<typename T>
T MyVector<T>::at(int i)
{
return data[i];
}
This has essentially the same form as f above, as it also returns a T (an employee* in your case). This is why the compiler complains.
And that complaint is helpful: Even if the compiler wouldn’t complain, the code would not dio what you almost certainly intended. The return statement returns a copy of the object data[i]. Thus if the statement payment.at(i)=NULL; had compiled, what would actually happen would be the following:
- The internal object
data[i](or however you called it in your code) is copied and the temporary copy returned. - The statement assigned that temporary copy, but leaves the original object in
MyVectorunchanged. - The temporary copy gets destructed, leaving no trace of your assignment.
This is almost certainly not what you wanted. You wanted to change the internal object. To do so, you have to return a reference to that object. A reference refers to the object it was initialized with instead of making a copy. Correspondingly, a reference, even when returned, is an lvalue (since C++11 there’s a second type of reference which behaves differently, but we don’t need to care about that here). Your corrected function then reads
template<typename T>
T& MyVector<T>::at(int i)
{
return data[i];
}
and with that definition, payment.at(i)=NULL; not only compiles, but actually does what you want: Change the internally stored i-th pointer in payment to NULL.
The message says that you try to assign to an expression which is not an lvalue. For built-in types, you can only assign to lvalues (that’s where the name comes from: lvalue = value that can be on the left hand side of the assignment operator, while rvalue = value that must be on the right hand side of the assignment operator).
So what is an lvalue or an rvalue? Consider the following code:
int a;
a = 3;
In this assignment a is an lvalue (if it weren’t, the compiler would complain). That is, the expression a refers to an object which can be modified. On the other hand, 3 is an rvalue, that is, basically a value. Of course you cannot assign to 3; the compiler would complain about the statement 3=a; with exactly the same message you got in your code.
So as a first approximation, an lvalue designates an object, while an rvalue designates a value. Note that this is also true for assignment of the form
a = b;
where b also is a variable. What happens here is the so-called lvalue to rvalue conversion: What is assigned is not the object b, but its current value.
Now consider the following case:
int f();
f() = 3;
Here you might argue that the function f does return an object (if you use some user-defined type, you even can see its construction/destruction). But the compiler still complains with the message you got. Why?
Well, even if you consider f to return an object, it is a temporary object which will go away immediately. So it does not make much sense to assign a value because you cannot do anything with it anyway afterwards.
Therefore here’s the second rule:
Whenever there’s an expression which produces a temporary object, C++ defines that expression as rvalue.
And now we come to the definition of MyVector::at() which you did not show, but which, according to the error message, probably looks similar to this:
template<typename T>
T MyVector<T>::at(int i)
{
return data[i];
}
This has essentially the same form as f above, as it also returns a T (an employee* in your case). This is why the compiler complains.
And that complaint is helpful: Even if the compiler wouldn’t complain, the code would not dio what you almost certainly intended. The return statement returns a copy of the object data[i]. Thus if the statement payment.at(i)=NULL; had compiled, what would actually happen would be the following:
- The internal object
data[i](or however you called it in your code) is copied and the temporary copy returned. - The statement assigned that temporary copy, but leaves the original object in
MyVectorunchanged. - The temporary copy gets destructed, leaving no trace of your assignment.
This is almost certainly not what you wanted. You wanted to change the internal object. To do so, you have to return a reference to that object. A reference refers to the object it was initialized with instead of making a copy. Correspondingly, a reference, even when returned, is an lvalue (since C++11 there’s a second type of reference which behaves differently, but we don’t need to care about that here). Your corrected function then reads
template<typename T>
T& MyVector<T>::at(int i)
{
return data[i];
}
and with that definition, payment.at(i)=NULL; not only compiles, but actually does what you want: Change the internally stored i-th pointer in payment to NULL.
The message says that you try to assign to an expression which is not an lvalue. For built-in types, you can only assign to lvalues (that’s where the name comes from: lvalue = value that can be on the left hand side of the assignment operator, while rvalue = value that must be on the right hand side of the assignment operator).
So what is an lvalue or an rvalue? Consider the following code:
int a;
a = 3;
In this assignment a is an lvalue (if it weren’t, the compiler would complain). That is, the expression a refers to an object which can be modified. On the other hand, 3 is an rvalue, that is, basically a value. Of course you cannot assign to 3; the compiler would complain about the statement 3=a; with exactly the same message you got in your code.
So as a first approximation, an lvalue designates an object, while an rvalue designates a value. Note that this is also true for assignment of the form
a = b;
where b also is a variable. What happens here is the so-called lvalue to rvalue conversion: What is assigned is not the object b, but its current value.
Now consider the following case:
int f();
f() = 3;
Here you might argue that the function f does return an object (if you use some user-defined type, you even can see its construction/destruction). But the compiler still complains with the message you got. Why?
Well, even if you consider f to return an object, it is a temporary object which will go away immediately. So it does not make much sense to assign a value because you cannot do anything with it anyway afterwards.
Therefore here’s the second rule:
Whenever there’s an expression which produces a temporary object, C++ defines that expression as rvalue.
And now we come to the definition of MyVector::at() which you did not show, but which, according to the error message, probably looks similar to this:
template<typename T>
T MyVector<T>::at(int i)
{
return data[i];
}
This has essentially the same form as f above, as it also returns a T (an employee* in your case). This is why the compiler complains.
And that complaint is helpful: Even if the compiler wouldn’t complain, the code would not dio what you almost certainly intended. The return statement returns a copy of the object data[i]. Thus if the statement payment.at(i)=NULL; had compiled, what would actually happen would be the following:
- The internal object
data[i](or however you called it in your code) is copied and the temporary copy returned. - The statement assigned that temporary copy, but leaves the original object in
MyVectorunchanged. - The temporary copy gets destructed, leaving no trace of your assignment.
This is almost certainly not what you wanted. You wanted to change the internal object. To do so, you have to return a reference to that object. A reference refers to the object it was initialized with instead of making a copy. Correspondingly, a reference, even when returned, is an lvalue (since C++11 there’s a second type of reference which behaves differently, but we don’t need to care about that here). Your corrected function then reads
template<typename T>
T& MyVector<T>::at(int i)
{
return data[i];
}
and with that definition, payment.at(i)=NULL; not only compiles, but actually does what you want: Change the internally stored i-th pointer in payment to NULL.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
#include "stdafx.h" #include "Tic Tac Toe.h" #define MAX_LOADSTRING 100 // Глобальные переменные: HINSTANCE hInst; // текущий экземпляр TCHAR szTitle[MAX_LOADSTRING]; // Текст строки заголовка TCHAR szWindowClass[MAX_LOADSTRING]; // имя класса главного окна RECT rect; HBITMAP hbitX, hbitO; int x, y; struct Cell // структура для одной ячейки на поле { bool fill; int left, top, right, bottom; char flag ; }; int coord [36] = {20,20,145,125,165,20,290,125,310,20,450,125,20,140,145,290,165,140,290,290,310,140,450,290,20,280,145,450,165,280,290,450,310,280,450,450}; //массив координат для вставки битмапа Cell cells [3][3]; // Отправить объявления функций, включенных в этот модуль кода: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPTSTR lpCmdLine, _In_ int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: разместите код здесь. MSG msg; HACCEL hAccelTable; // Инициализация глобальных строк LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_TICTACTOE, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); for (int i = 0, z = 0; i<3; i++) { for(int j=0; j<3 && z < 36; j++) { cells[i][j].fill=false; cells[i][j].left = coord[z++]; cells[i][j].top = coord[z++]; cells[i][j].right = coord[z++]; cells[i][j].bottom = coord[z++]; } } // Выполнить инициализацию приложения: if (!InitInstance (hInstance, nCmdShow)) { return FALSE;} hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TICTACTOE)); // Цикл основного сообщения: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // ФУНКЦИЯ: MyRegisterClass() // НАЗНАЧЕНИЕ: регистрирует класс окна. ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TICTACTOE)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_TICTACTOE); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex); } // ФУНКЦИЯ: InitInstance(HINSTANCE, int) // НАЗНАЧЕНИЕ: сохраняет обработку экземпляра и создает главное окно. // КОММЕНТАРИИ: // В данной функции дескриптор экземпляра сохраняется в глобальной переменной, а также // создается и выводится на экран главное окно программы. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // Сохранить дескриптор экземпляра в глобальной переменной hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, 0,450 /*CW_USEDEFAULT*/, 450, NULL, NULL, hInstance, NULL); //указать размер окна if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // ФУНКЦИЯ: WndProc(HWND, UINT, WPARAM, LPARAM) // НАЗНАЧЕНИЕ: обрабатывает сообщения в главном окне. // WM_COMMAND - обработка меню приложения // WM_PAINT -Закрасить главное окно // WM_DESTROY - ввести сообщение о выходе и вернуться. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; HDC hDC = GetDC(hWnd); HDC hMemDC = CreateCompatibleDC(hDC); switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Разобрать выбор в меню: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_LBUTTONDOWN: x=LOWORD(lParam); y=HIWORD(lParam); for (int i=0; i<3; i++) { for(int j=0; j<3; j++) { if (x >= cells[i][j].left && x<= cells[i][j].right && y >= cells[i][j].top && y <= cells[i][j].bottom && cells[i][j].fill = false) { cells[i][j].flag = 'x';} } } break; case WM_RBUTTONDOWN: x=LOWORD(lParam); y=HIWORD(lParam); for (int i=0; i<3; i++) { for(int j=0; j<3; j++) { if (x >= cells[i][j].left && x<= cells[i][j].right && y >= cells[i][j].top && y <= cells[i][j].bottom && cells[i][j].fill = false) { cells[i][j].flag = 'o';} } } break; |
Хорошо, так что, игнорируя мое ленивое кодирование (это просто для того, чтобы заставить программу работать, я уберу ее после того, как она заработает). Я настроил пару операторов if, которые будут генерировать исключения, если я не получу желаемый ввод.
#include<string>
#include<iostream>
using namespace std;
int main()
{
bool flag = false;
int month, day, year;
void header();
class monthClassException
{
public:
monthClassException()
{
message = "Invalid Month";
}
monthClassException(string str)
{
message = str;
}
string what()
{
return message;
}
private:
string message;
};
class dayClassException
{
};
class yearClassException
{
};header();
do
{
try
{
cout << "Please enter your date of birth (MM-DD-YYYY): " << endl;
cin >> month;
cin.ignore(10,'-');
cin >> day;
cin.ignore(10,'-');
cin >> year;if (month > 12 || month < 1)
throw monthClassException("Invalid Month Entry");
if( ((month == 4 || month == 6 || month == 9 || month == 11) && day > 30) || day < 1)
throw dayClassException();
else if ( ((month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12 ) && day > 31) || day < 1)
throw dayClassException();
else if (month == 2 && year % 4 != 0 && day > 28)
throw dayClassException();
else if((month == 2 && year % 4 = 0) && day > 29)
throw dayClassException();
}
catch(monthClassException mCEO)
{
cout << mCEO.what() << endl;
system("pause");
}
catch(dayClassException)
{
cout << "Invalid Day Entered for Selected Month" << endl;
system("pause");
}
catch(yearClassException yCEO)
{
}
}while(!flag);return 0;
}
Я получаю свою ошибку в этом последнем исключении:
else if((month == 2 && year % 4 = 0) && day > 29)
throw dayClassException();
он говорит, что месяц — недопустимое l-значение (почему сейчас? В самом конце, после того, как я его уже использовал — катастрофически, я признаю.) Это может быть чем-то действительно очевидным, что я не вижу, потому что я один кто это закодировал, или это может быть потому, что я действительно сумасшедший, если заявления где-то напутали.
Есть идеи?
-3
Решение
Вот ошибка:
year % 4 = 0
ты наверное хотел написать ==
4
Другие решения
= оператор как в
year % 4 = 0
означает назначение, а не сравнение. Отсюда твоя ошибка.
Исправить это
year % 4 == 0
0
У тебя есть year % 4 = 0,
Я думаю, что у вас есть опечатка: вы можете хотеть year % 4 == 0,
Кроме того, я предпочитаю использовать скобки, чтобы сделать код более понятным:
...
else if ((month == 2) && (year % 4 == 0) && (day > 29)) {
throw dayClassException();
}
0
У вас есть оператор присваивания = в вашем состоянии вместо оператора сравнения ==,
Это довольно ясно логическая ошибка. Тем не менее, почему это компилятор ошибка? В конце концов, C ++ позволяет присваивать внутри условия, и это то, что вы могли бы законно делать.
В твоем случае, month == 2 && year % 4 = 0 обрабатывается как ((month == 2) && (year % 4)) = 0 (увидеть Приоритет оператора C ++). Это выражение в скобках оценивается как временное. Но левая часть оператора присваивания должна ссылаться на адрес памяти, на который вы можете записать ( л-значение). Таким образом, ваш код недействителен по той же причине, что 3 = 3 является недействительным. Visual Studio вызывает эту ошибку C2106.
0
В связи с этим предлагается всегда указывать константу в левой части оператора сравнения. Это помогает предотвратить логические ошибки. В качестве примера рассмотрим код
if year == 0
и по ошибке вы написали:
if year = 0
результат был бы логической ошибкой.
Вместо этого поместите постоянную 0 на левой стороне, так что
if 0 = year
будет генерировать синтаксическую ошибку при компиляции, что не позволит вам совершить логическую ошибку (что может быть сложнее отладить)
0
Задание заключалось в том, чтобы переделать структуру под стек, но в функции vvod в 40 строке «p->marka = m;» выдает ошибку «левый операнд должен быть левосторонним значением». Не могу понять, в чем ошибка
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct autoservis
{
int num;
char marka[50];
int probeg;
struct autoservis *next;
};
typedef struct autoservis St;
St *last = NULL;
int i, k, n, pr;
char m[50];
void vvod()
{
St *p;
p = new St;
printf("Vvedite kol-vo avtomobilej: ");
scanf_s("%d", &k);
if (p != 0)
{
for (i = 0; i < k; i++)
{
puts("Vvedite registrazionniy nomer: ");
scanf_s("%d", &n);
p->num = n;
puts("Vvedite marku: ");
fflush(stdin);
gets_s(m);
p->marka = m;
printf("Vvedite probeg: ");
scanf_s("%d", &pr);
p->probeg = pr;
p->next = last;
last = p;
}
}
else printf("Oshibka pri vidilenii pamjatin");
}
void poisk()
{
St *psk = last;
int nomer;
if (psk == NULL){
printf("Net avtomobilejn");
}
else
{
printf("Vvedite reg. nomer: n");
scanf_s("%d", &nomer);
while (psk != NULL)
if (psk->num == nomer)
{
printf("Registrazionniy nomer: %d n", psk->num);
printf("Marka: %s n", psk->marka);
printf("Probeg: %d n", psk->probeg);
}
else
psk = psk->next;
}
}
void udalenie()
{
St *po;
po = new St;
po = last;
last = last->next;
free(po);
printf("Udalenije vipolnenon");
}
void vivod()
{
St *o = last;
if (o == NULL) printf("Stek pustn");
else
{
printf("Stek: n");
while (o != NULL)
{
printf("Reg. nomer: %d, Marka: %s, Probeg: %dn", o->num, o->marka, o->probeg);
o = o->next;
}
printf("n");
}
}
int check()
{
return (last == NULL);
}
int menu()
{
int ch;
printf("n Menu: n");
printf("1. Vvod massiva structur n");
printf("2. Poisk v massive structyr po zadannomy parametry n");
printf("3. Ydalenie structuri iz massiva n");
printf("4. Vivod structuri n");
printf("5. Vikhodn");
printf("t Vash vibor: ");
scanf_s("%d", &ch);
return ch;
}
int main()
{
while (1)
{
switch (menu())
{
case 1:
vvod();
break;
case 2:
poisk();
break;
case 3:
if (!(check())){
udalenie();
break;
}
else{
printf("Stek pustn");
break;
}
case 4:
vivod();
break;
case 5:
return 0;
default:
printf("n");
break;
}
}
}
