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
MyVector
unchanged. - 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
MyVector
unchanged. - 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
MyVector
unchanged. - 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
.
Содержание
- ошибка C2106: ‘=’: левый операнд должен иметь значение l
- 4 ответа
- ошибка C2106: ‘=’: левый операнд должен быть l-значением
- 4 ответы
- ошибка C2106: ‘=’: левый операнд должен иметь l-значение в C
- 3 ответы
- Ошибка C2106: ‘=’: левый операнд должен быть l-value
ошибка C2106: ‘=’: левый операнд должен иметь значение l
Рассматривая другие вопросы, касающиеся ошибки C2106, я по-прежнему теряю то, что проблема с моим кодом. При компиляции я получаю следующие ошибки:
c:driver.cpp(99): ошибка C2106: ‘=’: левый операнд должен быть l-value
c:driver.cpp(169): ошибка C2106: ‘=’: левый операнд должен быть l-value
Строка кода выглядит следующим образом:
Я не понимаю, почему эта ошибка возникает. В этом проекте я изменил свой driver.cpp из массива указателей на объект-работник на пользовательский векторный шаблон, который я создал. Я объявляю вектор следующим образом:
Любая помощь приветствуется.
4 ответа
Эта ошибка возникает по той же причине, что вы не можете сделать что-то вроде этого:
Ваша версия Vector::at должна возвращать ссылку, а не значение.
Lvalues называются Lvalues, потому что они могут появляться слева от задания. Rvalues не могут появляться с левой стороны, поэтому мы называем их rvalues. Вы не можете назначить 3 на 36 , потому что 36 не является lvalue, это rvalue, временным. У него нет адреса памяти. По той же причине вы не можете назначить NULL payroll.at(i) .
Что это должно быть:
В сообщении говорится, что вы пытаетесь присвоить выражение, которое не является значением lvalue. Для встроенных типов вы можете назначать только значения lvalues (где происходит имя: lvalue = значение, которое может находиться в левой части оператора присваивания, тогда как rvalue = значение, которое должно быть в правой части оператор присваивания).
Итак, что такое lvalue или rvalue? Рассмотрим следующий код:
В этом присваивании a есть значение lvalue (если бы оно не было, компилятор будет жаловаться). То есть выражение a относится к объекту, который может быть изменен. С другой стороны, 3 является значением r, то есть в основном значением. Конечно, вы не можете назначить 3 ; компилятор будет жаловаться на утверждение 3=a; с тем же сообщением, которое вы получили в вашем коде.
Итак, в первом приближении lvalue обозначает объект, а rvalue обозначает значение. Заметим, что это также верно для назначения формы
где b также является переменной. Здесь происходит так называемое преобразование lvalue в rvalue: назначено не объект b , а его текущее значение.
Теперь рассмотрим следующий случай:
Здесь вы можете утверждать, что функция f возвращает объект (если вы используете определенный пользовательский тип, вы даже можете увидеть его конструкцию/уничтожение). Но компилятор все еще жалуется на ваше сообщение. Почему?
Ну, даже если вы считаете, что f возвращает объект, это временный объект, который немедленно исчезнет. Поэтому не имеет смысла назначать значение, потому что после этого вы ничего не можете с ним поделать.
Поэтому здесь второе правило:
Всякий раз, когда есть выражение, которое создает временный объект, С++ определяет это выражение как rvalue.
И теперь мы переходим к определению MyVector::at() , которое вы не показывали, но которое, согласно сообщению об ошибке, похоже выглядит примерно так:
Это по существу тот же самый вид, что и f выше, так как он также возвращает T (an employee* в вашем случае). Вот почему компилятор жалуется.
И эта жалоба полезна: даже если компилятор не будет жаловаться, код не будет делать то, что вы почти наверняка запланировали. Оператор return возвращает копию объекта data[i] . Таким образом, если команда payment.at(i)=NULL; была скомпилирована, что бы произошло на самом деле, было бы следующее:
- Внутренний объект data[i] (или, тем не менее, вы его вызывали в коде) копируется и возвращается временная копия.
- Оператор присваивает эту временную копию, но исходный объект в MyVector не изменяется.
- Временная копия разрушается, не оставляя следов вашего назначения.
Это почти наверняка не то, что вы хотели. Вы хотите изменить внутренний объект. Для этого вам нужно вернуть ссылку на этот объект. Ссылка ссылается на объект, который был инициализирован, вместо того, чтобы делать копию. Соответственно, ссылка, даже когда возвращается, является значением lvalue (поскольку С++ 11 содержит второй тип ссылок, который ведет себя по-другому, но здесь нам не нужно заботиться). Затем ваша исправленная функция читает
Источник
ошибка C2106: ‘=’: левый операнд должен быть l-значением
Глядя на другие вопросы, касающиеся ошибки C2106, я все еще не понимаю, в чем проблема с моим кодом. При компиляции получаю следующие ошибки:
c:driver.cpp(99): ошибка C2106: ‘=’: левый операнд должен быть l-значением
c:driver.cpp(169): ошибка C2106: ‘=’: левый операнд должен быть l-значением
Строка кода выглядит следующим образом:
Я не могу понять, почему эта ошибка выдается. В этом проекте я изменил свой файл driver.cpp из массива указателей объектов сотрудников на собственный шаблон Vector, который я сделал. Я объявляю Вектор следующим образом.
Любая помощь приветствуется .
задан 29 июля ’13, 18:07
Что делает MyVector::at return? — tohava
Моя догадка : YourVector::at() должен возвращаться по значению, что является проблемой. — Nawaz
@tohava вот что он возвращает. ‘return myArray[n];’ если ссылка не превышает размер вектора, она возвращает значение, которое было передано в функцию. — KQball
@KQball: Что такое тип возврата (что определяет КАК Вы возвращаетесь почему вы вернетесь)? — Nawaz
4 ответы
Эта ошибка возникает по той же причине, по которой вы не можете сделать что-то вроде этого:
Ваша версия Vector::at должен возвращать ссылку, а не значение.
Lvalues называются Lvalues, потому что они могут появляться слева от присваивания. R-значения не могут отображаться слева, поэтому мы называем их r-значениями. Вы не можете назначить 3 в 36 , так как: 36 это не lvalue, это rvalue, временное. У него нет адреса памяти. По той же причине нельзя назначить NULL в payroll.at(i) .
Каким должно быть:
Создан 29 июля ’13, 19:07
Ну, я смотрю документы, и там написано, что они возвращают ссылку. ты уверен? — Льюс Терин
@LewsTherin Вы правы, но это пользовательская реализация вектора — user123
В предположении прямонаправленного размещения памяти параметр at должно быть unsigned . — Пиксельхимик
Параметр at вероятно должно быть size_t , но это не самая большая проблема здесь. — Свен
Я не имею в виду, что есть проблема с ответом, я имел в виду, что это было помимо сути исходного вопроса. Извините за путаницу. — Свен
В сообщении говорится, что вы пытаетесь присвоить выражение, которое не является lvalue. Для встроенных типов можно присваивать только lvalue (отсюда и название: lvalue = значение, которое может быть на оставил стороны оператора присваивания, а rvalue = значение, которое должно быть в правильно стороны оператора присваивания).
Итак, что такое lvalue или rvalue? Рассмотрим следующий код:
В этом задании a является lvalue (если бы это было не так, компилятор жаловался бы). То есть выражение a относится к объекту, который может быть изменен. С другой стороны, 3 является rvalue, то есть, в основном, значением. Конечно, вы не можете назначить 3 ; компилятор будет жаловаться на оператор 3=a; с точно таким же сообщением, которое вы получили в своем коде.
Так как первое приближение, lvalue обозначает объект, а rvalue обозначает значение. Обратите внимание, что это верно и для присваивания вида
в котором b также является переменной. Здесь происходит так называемое преобразование lvalue в rvalue: присваивается не объект b , но его текущее значение.
Теперь рассмотрим следующий случай:
Здесь вы можете возразить, что функция f действительно возвращает объект (если вы используете определенный пользователем тип, вы даже можете увидеть его построение/уничтожение). Но компилятор все еще жалуется на полученное вами сообщение. Почему?
Ну, даже если учесть f вернуть объект, это временный объект, который сразу исчезнет. Таким образом, нет особого смысла присваивать значение, потому что вы все равно ничего не сможете сделать с ним впоследствии.
Поэтому второе правило:
Всякий раз, когда есть выражение, которое производит временный объект, C++ определяет это выражение как rvalue.
И вот мы подошли к определению MyVector::at() который вы не показали, но который, судя по сообщению об ошибке, вероятно, выглядит примерно так:
Это имеет в основном ту же форму, что и f выше, так как он также возвращает T ( employee* в твоем случае). Вот почему компилятор жалуется.
И эта жалоба полезна: даже если компилятор не будет жаловаться, код почти наверняка не сделает то, что вы намеревались. return инструкция возвращает копия объекта data[i] . Таким образом, если утверждение payment.at(i)=NULL; скомпилирован, то на самом деле произойдет следующее:
- Внутренний объект data[i] (или, как бы вы это ни называли в своем коде) копироваться и временная копия вернулась.
- В заявлении указано, что временная копия, но оставляет исходный объект в MyVector без изменений.
- Временная копия уничтожается, не оставляя следов вашего задания.
Это почти наверняка не то, что вы хотели. Вы хотели изменить внутренний объект. Для этого нужно вернуть ссылка к этому объекту. Ссылка относится к объекту, которым она была инициализирована, а не к копии. Соответственно, ссылка, даже когда она возвращается, является lvalue (поскольку в C++11 есть второй тип ссылки, который ведет себя по-другому, но здесь нам это не нужно). Затем ваша исправленная функция читает
Источник
ошибка C2106: ‘=’: левый операнд должен иметь l-значение в C
Я пишу код, в котором мне нужно добавить значение в абстрактную таблицу данных, но я не уверен, почему я не могу, поскольку он показывает ошибку «ошибка C2106: ‘=’: левый операнд должен иметь значение l».
Я поискал в Интернете, но не смог найти для меня слишком относительного решения.
Я был бы очень признателен за любой намек на это.
Опубликуйте определение top_string — Luchian Grigore
Пожалуйста, покажите нам, что table->item[table->item_count].index и table->item[table->item_count].other на самом деле есть. — m0skit0
Как сделать декларацию table->item[table->item_count].index выглядит как? Если это также массив, то его можно назначить, вам нужно скопировать данные с помощью некоторой функции (например, memcpy ). То же самое касается table->item[table->item_count].other также. — Some programmer dude
Если вы сомневаетесь, вы всегда должны пытаться создать минимальный тестовый пример, чтобы увидеть, имеет ли смысл то, что вы делаете. В вашем случае это будет что-то вроде void f(const char a[10]) < char b[10]; b = a; >. Это сделало бы вопрос менее шумным, а также дало бы вам более узкое представление о том, в чем может заключаться проблема. — Kerrek SB
3 ответы
Поля index и other являются массивами, вы не можете назначать массивы. Вам придется скопировать их с помощью memcpy .
Другой вариант — иметь top_add Получать pair вместо двух по отдельности. Тогда вы могли бы назначить struct .
Источник
Ошибка C2106: ‘=’: левый операнд должен быть l-value
Рассматривая другие вопросы, касающиеся ошибки C2106, я по-прежнему теряю то, что проблема с моим кодом. При компиляции я получаю следующие ошибки:
c:driver.cpp(99): ошибка C2106: ‘=’: левый операнд должен быть l-value
c:driver.cpp(169): ошибка C2106: ‘=’: левый операнд должен быть l-value
Строка кода выглядит следующим образом:
Я не понимаю, почему эта ошибка возникает. В этом проекте я изменил свой driver.cpp из массива указателей на объект-работник на пользовательский векторный шаблон, который я создал. Я объявляю вектор следующим образом:
Любая помощь приветствуется.
Эта ошибка возникает по той же причине, что вы не можете сделать что-то вроде этого:
Ваша версия Vector::at должна возвращать ссылку, а не значение.
Lvalues называются Lvalues, потому что они могут появляться слева от задания. Rvalues не могут появляться с левой стороны, поэтому мы называем их rvalues. Вы не можете назначить 3 на 36 , потому что 36 не является lvalue, это rvalue, временным. У него нет адреса памяти. По той же причине вы не можете назначить NULL payroll.at(i) .
Что это должно быть:
В сообщении говорится, что вы пытаетесь присвоить выражение, которое не является значением lvalue. Для встроенных типов вы можете назначать только значения lvalues (где происходит имя: lvalue = значение, которое может находиться в левой части оператора присваивания, тогда как rvalue = значение, которое должно быть в правой части оператор присваивания).
Итак, что такое lvalue или rvalue? Рассмотрим следующий код:
В этом присваивании a есть значение lvalue (если бы оно не было, компилятор будет жаловаться). То есть выражение a относится к объекту, который может быть изменен. С другой стороны, 3 является значением r, то есть в основном значением. Конечно, вы не можете назначить 3 ; компилятор будет жаловаться на утверждение 3=a; с тем же сообщением, которое вы получили в вашем коде.
Итак, в первом приближении lvalue обозначает объект, а rvalue обозначает значение. Заметим, что это также верно для назначения формы
где b также является переменной. Здесь происходит так называемое преобразование lvalue в rvalue: назначено не объект b , а его текущее значение.
Теперь рассмотрим следующий случай:
Здесь вы можете утверждать, что функция f возвращает объект (если вы используете определенный пользовательский тип, вы даже можете увидеть его конструкцию/уничтожение). Но компилятор все еще жалуется на ваше сообщение. Почему?
Ну, даже если вы считаете, что f возвращает объект, это временный объект, который немедленно исчезнет. Поэтому не имеет смысла назначать значение, потому что после этого вы ничего не можете с ним поделать.
Поэтому здесь второе правило:
Всякий раз, когда есть выражение, которое создает временный объект, С++ определяет это выражение как rvalue.
И теперь мы переходим к определению MyVector::at() , которое вы не показывали, но которое, согласно сообщению об ошибке, похоже выглядит примерно так:
Это по существу тот же самый вид, что и f выше, так как он также возвращает T (an employee* в вашем случае). Вот почему компилятор жалуется.
И эта жалоба полезна: даже если компилятор не будет жаловаться, код не будет делать то, что вы почти наверняка запланировали. Оператор return возвращает копию объекта data[i] . Таким образом, если команда payment.at(i)=NULL; была скомпилирована, что бы произошло на самом деле, было бы следующее:
- Внутренний объект data[i] (или, тем не менее, вы его вызывали в коде) копируется и возвращается временная копия.
Оператор присваивает эту временную копию, но исходный объект в MyVector не изменяется.
Временная копия разрушается, не оставляя следов вашего назначения.
Это почти наверняка не то, что вы хотели. Вы хотите изменить внутренний объект. Для этого вам нужно вернуть ссылку на этот объект. Ссылка ссылается на объект, который был инициализирован, вместо того, чтобы делать копию. Соответственно, ссылка, даже когда возвращается, является значением lvalue (поскольку С++ 11 содержит второй тип ссылок, который ведет себя по-другому, но здесь нам не нужно заботиться). Затем ваша исправленная функция читает
Источник
BoBaH26 30 / 30 / 5 Регистрация: 02.12.2010 Сообщений: 255 |
||||
1 |
||||
20.09.2011, 23:20. Показов 8815. Ответов 39 Метки нет (Все метки)
Здравствуйте, при попытке символьному элементу структуры (char name [30]) присвоить такой же символьный элемент выдается ошибка C2106 — левый операнд должен быть левосторонним значением. Вот фрагмент листинга, на всякий случай с описанием самой структуры:
Заранее спасибо!
__________________
0 |
794 / 546 / 61 Регистрация: 11.05.2010 Сообщений: 1,298 Записей в блоге: 1 |
|
20.09.2011, 23:37 |
2 |
BoBaH26, массивы массивам не присваиваются. Для копирования строк используйте strcpy.
0 |
186 / 186 / 21 Регистрация: 08.01.2011 Сообщений: 1,139 |
|
20.09.2011, 23:38 |
3 |
name — это указатель на строку.
0 |
30 / 30 / 5 Регистрация: 02.12.2010 Сообщений: 255 |
|
20.09.2011, 23:39 [ТС] |
4 |
Сейчас попробую…
0 |
talis |
20.09.2011, 23:40
|
Не по теме: Chelioss, это не указатель. Массив чистой воды
char name [30];
0 |
30 / 30 / 5 Регистрация: 02.12.2010 Сообщений: 255 |
|
20.09.2011, 23:41 [ТС] |
6 |
Chelioss, так а как тогда? Через copy, как сказал talis?
0 |
186 / 186 / 21 Регистрация: 08.01.2011 Сообщений: 1,139 |
|
20.09.2011, 23:41 |
7 |
Не по теме: Chelioss, это не указатель. Массив чистой воды Не правильно. name — это указатель на массив, причем name — это константный указатель.
0 |
30 / 30 / 5 Регистрация: 02.12.2010 Сообщений: 255 |
|
20.09.2011, 23:41 [ТС] |
8 |
Да, кстати, не заметил, это символьный массив.
0 |
186 / 186 / 21 Регистрация: 08.01.2011 Сообщений: 1,139 |
|
20.09.2011, 23:42 |
9 |
Chelioss, так а как тогда? Через copy, как сказал talis? Да, либо самому вручную каждый элемент присвоить.
0 |
30 / 30 / 5 Регистрация: 02.12.2010 Сообщений: 255 |
|
20.09.2011, 23:43 [ТС] |
10 |
Да, либо самому вручную каждый элемент присвоить. Ну это не есть хорошо, т.к. у меня массив из структур, а мне его надо отсортировать, и для каждого MasList[i].name писать вручную…. Можно с ума сойти..
0 |
794 / 546 / 61 Регистрация: 11.05.2010 Сообщений: 1,298 Записей в блоге: 1 |
|
20.09.2011, 23:44 |
11 |
Chelioss, где он объявлен как указатель? min — это объект типа List. В struct List есть объявление char name [30];. Соответственно, min.name — массив char из 30 элементов. Добавлено через 24 секунды
Да, либо самому вручную каждый элемент присвоить. Не имеет смысла. Есть библиотечные функции для копирования строк и памяти.
0 |
Chelioss 186 / 186 / 21 Регистрация: 08.01.2011 Сообщений: 1,139 |
||||
20.09.2011, 23:46 |
12 |
|||
Ну это не есть хорошо, т.к. у меня массив из структур, а мне его надо отсортировать, и для каждого MasList[i].name писать вручную…. Можно с ума сойти.. Можно самому написать функцию подобной strcpy. Ну или используйте strcpy. Добавлено через 1 минуту
Chelioss, где он объявлен как указатель?
Конечно, надо по другому объяснять, а не примеры приводить, но я просто знаю без доказательства)
0 |
30 / 30 / 5 Регистрация: 02.12.2010 Сообщений: 255 |
|
20.09.2011, 23:48 [ТС] |
13 |
Не совсем понял с пунктом 1
0 |
794 / 546 / 61 Регистрация: 11.05.2010 Сообщений: 1,298 Записей в блоге: 1 |
|
20.09.2011, 23:50 |
14 |
char *ptr = name; // работает. Почему? Потому, что name — это char *. Работает благодаря приведению типов. Объявление смотрите — char name[30].
0 |
Chelioss 186 / 186 / 21 Регистрация: 08.01.2011 Сообщений: 1,139 |
||||
20.09.2011, 23:50 |
15 |
|||
Не совсем понял с пунктом 1 Вы про
?
0 |
talis 794 / 546 / 61 Регистрация: 11.05.2010 Сообщений: 1,298 Записей в блоге: 1 |
||||
20.09.2011, 23:52 |
16 |
|||
Какой тип объявлен?
0 |
186 / 186 / 21 Регистрация: 08.01.2011 Сообщений: 1,139 |
|
20.09.2011, 23:52 |
17 |
Работает благодаря приведению типов. Объявление смотрите — char name[30]. А что такое name? без []? Он по вашему мнению вообще не существует без []. А со [] — это всего лишь i-тый символ, а не массив.
0 |
30 / 30 / 5 Регистрация: 02.12.2010 Сообщений: 255 |
|
20.09.2011, 23:54 [ТС] |
18 |
char *ptr = name;
0 |
794 / 546 / 61 Регистрация: 11.05.2010 Сообщений: 1,298 Записей в блоге: 1 |
|
20.09.2011, 23:55 |
19 |
Chelioss, по моему мнению (и позвольте мне самому его высказывать), name без [] — это массив из 30-ти char, как и объявлено выше. А к указателю оно приводится автоматически благодаря приведению типов. Добавлено через 24 секунды
char *ptr = name; Да. Адрес первого элемента массива name.
0 |
186 / 186 / 21 Регистрация: 08.01.2011 Сообщений: 1,139 |
|
20.09.2011, 23:59 |
20 |
talis
0 |
Хорошо, так что, игнорируя мое ленивое кодирование (это просто для того, чтобы заставить программу работать, я уберу ее после того, как она заработает). Я настроил пару операторов 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