Программа по вычислениям полностью устраивает, она перемножает 2 матрицы указанного размера с рандомными числами, она запускается и правильно считает, но показывает, что есть ошибки типа: cin, cout, system не являются однозначными, всего 17 ошибок, подчеркивает красным эти операторы, как это убрать?
#include <iostream>
#include <ctime>
#include <iomanip>
using namespace std;
int main()
{
setlocale(LC_ALL, "Russian");
int** P1, ** P2, ** P3, n, m;
cout << "Введите кол-во строк матрицы: ";
cin >> n;
cout << "Введите кол-во столбцов матрицы: ";
cin >> m;
P1 = new int* [n];
for (int i = 0; i < n; i++)
P1[i] = new int[m];
srand(time(0));
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++) //рандом 1 матрицы
P1[i][j] = rand() % 10;
for (int i = 0; i < n; i++)
{
cout << endl; //вывод 1 матрицы
for (int j = 0; j < m; j++)
{
cout << setw(3) << P1[i][j] << "t";
}
}
cout << endl;
int k;
cout << "Введите кол-во столбцов 2 матрицы: ";
cin >> k;
P2 = new int* [k];
for (int i = 0; i < m; i++)
P2[i] = new int[k];
for (int i = 0; i < m; i++)
for (int j = 0; j < k; j++) //рандом 2 матрицы
P2[i][j] = rand() % 10;
for (int i = 0; i < m; i++)
{
cout << endl; //вывод 2 матрицы
for (int j = 0; j < k; j++)
{
cout << setw(3) << P2[i][j] << "t";
}
}
cout << endl;
P3 = new int* [n];
for (int i = 0; i < n; i++)
P3[i] = new int[k];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < k; j++) //умножение матриц
{
P3[i][j] = 0;
for (int z = 0; z < m; z++)
P3[i][j] = P3[i][j] + P1[i][z] * P2[z][j];
}
}
cout << endl << "Результат умножения:" << endl;
for (int i = 0; i < n; i++) //вывод результата
умножения
{
cout << endl;
for (int j = 0; j < k; j++)
cout << setw(3) << P3[i][j] << "t";
}
cout << endl;
for (int i = 0; i < n; i++)
delete[] P1[i];
delete[] P1;
for (int i = 0; i < m; i++)
delete[] P2[i];
delete[] P2;
for (int i = 0; i < n; i++)
delete[] P3 [i];
delete[] P3;
system("pause");
return 0;
}
1 / 1 / 4
Регистрация: 01.10.2016
Сообщений: 247
1
15.06.2017, 20:47. Показов 68648. Ответов 1
Добрый день, при написании кода я столкнулся с проблемой, cout везде выбивает «
«cout» не является однозначным С++», как решить эту проблему?
Условие : «С помощью перегруженных функций реализуем задачу для различных типов массивов, например для типов int и float. «
Код:
| C++ | ||
|
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
- Forum
- General C++ Programming
- Cout is ambiguous?
Cout is ambiguous?
What does that mean? How do I fix it?
Post the actual error message, as well as the line of code which is causing the error.
Post your code so that it is [code]between code tags[/code] as this will give it syntax highlighting and line numbers.
Please copy and paste the exact error message, and indicate which line the error is talking about.
Last edited on
Well, I am working on this bank database project and whenever I post this part:
void addaccount()
{
ifstream inData;
ofstream outData;
string fileName;
string str;
cout << «Insert the name of the data file: «;
cin >> fileName;
inData.open(fileName); // Access the file of the name you had inputted
string lastName, firstName, type;
double balance;
inData >> lastName >> firstName >> balance >> type;
cout << «What file would you like to save the data in?: «;
cin >> fileName;
outData.open(fileName);
outData << str;
cout << «nEnter the customer’s last name:»;
cin >> lastName;
cout << «nnEnter the customer’s first name : «;
cin >> firstName;
cin.ignore();
cin.getline(50, firstName);
cout << «nEnter Type of The account (C/S) : «;
cin >> type;
type = toupper(type);
cout << «nEnter The Initial amount(>=500 for Saving and >=1000 for current ) : «;
cin >> deposit;
cout << «nnnAccount Created.»;
}
void deleteaccount();
{
account ac;
ifstream inFile;
ofstream outFile;
inFile.open(«account.dat», ios::binary);
if (!inFile)
{
cout << «File could not be open !! Press any Key…»;
return;
}
outFile.open(«Temp.dat», ios::binary);
inFile.seekg(0, ios::beg);
while (inFile.read(reinterpret_cast<char *> (&ac), sizeof(account)))
{
if (ac.retacno() != n)
{
outFile.write(reinterpret_cast<char *> (&ac), sizeof(account));
}
}
inFile.close();
outFile.close();
remove(«account.txt»);
rename(«Temp.txt», «account.txt»);
cout << «nntRecord Deleted ..»;
}
void search();
{
int seqSearch(const int list[], int listLength, int searchItem)
{
int loc;
bool found = false;
for (loc = 0; loc < listLength; loc++)
if (list[loc] == searchItem)
{
found = true;
break;
}
if (found)
return loc;
else
return -1;
}
into it, all the couts get the error message IntelliSense: «cout» is ambiguous.
Speaking of which, I really need help with that. I have a topic called ‘Bank Database’ I could really use help with.
IntelliSense errors aren’t compilation errors. Sometimes IntelliSense can get confused or out of date.
Go to Build -> Rebuild
You may also consider trying to prefix your ‘cout’ object with its namespace, ‘std’. In other words, wherever you’ve put
cout << "Information";
You may consider putting
std::cout << "Information";
Perhaps there are multiple objects called ‘cout’ in your program (or you’ve included external libraries which also have a cout object) and providing a namespace might give some clarification as to which one you mean.
Topic archived. No new replies allowed.
Дополнительные сведения о: Ошибка компилятора C2065
Решение
Поместите директиву
#include “stdafx.h”
прежде чем любые другие включают директивы.
7
Решение
прежде чем любые другие включают директивы.
Я только начал разбираться с плюсами. И тут же воткнулся в какой-то непонятный для меня косяк.
Вроде все верно. Но при компиляции ошибка:
Я почитал у вас тут похожие темы. Пишут, что область имен надо объявить, она есть. Вроде вообще все как надо. Я использую VS 2017 для написания кода. Объясните, пожалуйста, что не так.
Двоичное дерево поиска
Задание. Построение и обработка двоичных деревьев поиска. Реализовать программу, выполняющую следующий набор операций с деревьями поиска:
поиск вершины с заданным значением ключа с выводом счетчика числа появлений данного ключа
добавление новой вершины в соответствии со значением ее ключа или увеличение счетчика числа появлений
построчный вывод дерева в наглядном виде с помощью обратно-симметричного обхода
вывод всех вершин в одну строку по порядку следования ключей с указанием для каждой вершины значения ее счетчика появлений
удаление вершины с заданным значением ключа
Выдает (в VS 2012) следующие ошибки:

Т. Е. он утв-ет что count не является однозначным и не определен
Идентификатор не объявленThe identifier is undeclared
Если идентификатор является переменной или именем функции, его необходимо объявить перед тем, как его можно будет использовать.If the identifier is a variable or a function name, you must declare it before it can be used. Перед использованием функции в объявлении функции также должны быть включены типы его параметров.A function declaration must also include the types of its parameters before the function can be used. Если переменная объявлена с помощью auto , компилятор должен иметь возможность определить тип из его инициализатора.If the variable is declared using auto, the compiler must be able to infer the type from its initializer.
Если идентификатор является членом класса или структуры или объявлен в пространстве имен, он должен уточняться именем класса или структуры или именем пространства имен при использовании вне структуры, класса или области пространства имен.If the identifier is a member of a class or struct, or declared in a namespace, it must be qualified by the class or struct name, or the namespace name, when used outside the struct, class, or namespace scope. Кроме того, пространство имен должно быть помещено в область с помощью using директивы, такой как using namespace std; , или имя члена должно быть помещено в область с помощью using объявления, такого как using std::string; .Alternatively, the namespace must be brought into scope by a using directive such as using namespace std;, or the member name must be brought into scope by a using declaration, such as using std::string;. В противном случае неполное имя считается необъявленным идентификатором в текущей области.Otherwise, the unqualified name is considered to be an undeclared identifier in the current scope.
Если идентификатор является тегом для определяемого пользователем типа, например, class или struct , тип тега должен быть объявлен до его использования.If the identifier is the tag for a user-defined type, for example, a class or struct, the type of the tag must be declared before it can be used. Например, объявление struct SomeStruct { /*…*/ }; должно существовать, прежде чем можно будет объявить переменную SomeStruct myStruct; в коде.For example, the declaration struct SomeStruct { /*…*/ }; must exist before you can declare a variable SomeStruct myStruct; in your code.
Если идентификатор является псевдонимом типа, тип должен быть объявлен с помощью using объявления или typedef перед тем, как его можно будет использовать.If the identifier is a type alias, the type must be declared by using a using declaration or typedef before it can be used. Например, необходимо объявить, using my_flags = std::ios_base::fmtflags; прежде чем можно будет использовать my_flags в качестве псевдонима типа для std::ios_base::fmtflags .For example, you must declare using my_flags = std::ios_base::fmtflags; before you can use my_flags as a type alias for std::ios_base::fmtflags.
1. Статическая инициализация
При создании статической переменной, возникает вопрос, когда эта переменная будет инициализирована, сколько времени она проживёт и когда будет уничтожена? Статическая инициализация позволяет нам создать переменную, которая будет инициализирована до запуска программы со временем жизни в течение всей программы и уничтожении после завершения. Такие константные переменные не зависят от исполнения — они всегда существуют, создаются во время компиляции и располагаются в исполнимом файле (в бинарнике). Как результат: нулевые накладные расходы, ранняя диагностика проблем и безопасность. Вопрос об использовании статической инициализации напрямую зависит от предметной области разрабатываемого проекта — чем ниже уровень, тем соблазн использования выше, а иногда и критичен, тут скорость решает всё.
Как пример:
const std :: size_t tabsize = 64 ;int tab [ tabsize ] ;
Логические операторы
В то время как операторы сравнения используются для проверки конкретного условия: ложное оно или истинное, они могут проверить только одно условие за определенный промежуток времени. Но бывают ситуации, когда нужно протестировать сразу несколько условий. Например, чтобы узнать, выиграли ли мы в лотерею, нам нужно сравнить все цифры купленного билета с выигрышными. Если в лотерее 6 цифр, то нужно выполнить 6 сравнений, все из которых должны быть true.
Также иногда нам нужно знать, является ли хоть одно из нескольких условий истинным. Например, мы не пойдем сегодня на работу, если больны или слишком устали, или если выиграли в лотерею. Нам нужно проверить, является ли хоть одно из этих 3-х условий истинным. Как это сделать? С помощью логических операторов! Они позволяют проверить сразу несколько условий за раз.
В языке C++ есть 3 логических оператора:
| Оператор | Символ | Пример | Операция |
| Логическое НЕ | ! | !x | true, если x — false и false, если x — true |
| Логическое И | && | x && y | true, если x и y — true, в противном случае — false |
| Логическое ИЛИ | || | x || y | true, если x или y — true, в противном случае — false |
Короткий цикл вычислений
Для того, чтобы логическое И возвращало true, оба операнда должны быть истинными. Если первый операнд вычисляется как false, то оператор И должен сразу возвращать false независимо от результата второго операнда (даже без его обработки). Это называется коротким циклом вычисления (англ. «short circuit evaluation») и выполняется он, в первую очередь, в целях оптимизации.
Аналогично, если первый операнд логического ИЛИ является true, то и всё условие будет true (даже без обработки второго операнда).
Как и в случае с оператором ИЛИ, новички иногда путают логическое И (&&) с побитовым И (&).
Пример: сбой выведения типа C++/CLIExample: C++/CLI type deduction failure
Эта ошибка может возникать при вызове универсальной функции, если аргумент предполагаемого типа не может быть выведен из используемых параметров.This error can occur when calling a generic function, if the intended type argument cannot be deduced from the parameters used. Дополнительные сведения см. в разделе универсальные функции (C++/CLI).For more information, see Generic Functions (C++/CLI).
// C2065_b.cpp// compile with: cl /clr C2065_b.cppgeneric <typename ItemType>void G(int i) {}int main() { // global generic function call G<T>(10); // C2065 G<int>(10); // OK – fix with a specific type argument}
А где же побитовое исключающее ИЛИ (XOR)?
Побитовое исключающее ИЛИ (XOR) — это логический оператор, который используется в некоторых языках программирования для проверки на истинность нечётного количества условий.
| Побитовое исключающее ИЛИ (XOR) | ||
| Левый операнд | Правый операнд | Результат |
| false | false | false |
| false | true | true |
| true | false | true |
| true | true | false |
В языке C++ нет такого оператора. В отличии от логических И/ИЛИ, к XOR не применяется короткий цикл вычислений. Однако его легко можно сымитировать, используя оператор неравенства (!=):
|
if(a!=b)...// a XOR b (предполагается, что a и b имеют тип bool) |
Можно также расширить количество операндов:
|
if(a!=b!=c!=d)...// a XOR b XOR c XOR d (предполагается, что a, b, c и d имеют тип bool) |
Следует отметить, что вышеприведенные шаблоны XOR работают только, если операнды имеют логический (а не целочисленный) тип данных. Если вы хотите, чтобы это работало и с целыми числами, то используйте оператор static_cast.
Форма XOR, которая работает и с другими типами данных (с помощью оператора static_cast мы можем конвертировать любой тип данных в тип bool):
|
if(static_cast<bool>(a)!=static_cast<bool>(b)!=static_cast<bool>(c)!=static_cast<bool>(d))...// a XOR b XOR c XOR d, для любого типа, который может быть конвертирован в тип bool |
Позвольте мне предвосхитить это, сказав, что я включил (также относится к string, endl, и буквально все не работает); моя IDE не показывает ошибок, насколько синтаксис идет; и я не могу понять, почему эта проблема происходит? Он отлично работает в одном из моих других примеров кода C ++, которые я написал.
Поэтому я пытаюсь сделать небольшую игру, быков и коров. Мой основной код выглядит следующим образом:
Наконец, мой файл BullsAndCows.cpp:
Ошибки, которые я получаю, так как «cout не является членом std», символ cout не может использоваться в объявлении использования. До этого я использовал «использование пространства имен std», и это возвращало бы ошибки, такие как «BullsAndCows» не является пространством имен или классом (если это не класс, то я должен быть марсианином). Также кое-что о пропавшем «;» перед userInput, например, в моем коде main.cpp; что не имеет смысла, так как нет ничего, что не хватает этого. Я использую VS2017. Почему C ++ такой раздражающий язык для работы?
Решение
прежде чем любые другие включают директивы.
Я только начал разбираться с плюсами. И тут же воткнулся в какой-то непонятный для меня косяк.
Вроде все верно. Но при компиляции ошибка:
Я почитал у вас тут похожие темы. Пишут, что область имен надо объявить, она есть. Вроде вообще все как надо. Я использую VS 2017 для написания кода. Объясните, пожалуйста, что не так.
Двоичное дерево поиска
Задание. Построение и обработка двоичных деревьев поиска. Реализовать программу, выполняющую следующий набор операций с деревьями поиска:
поиск вершины с заданным значением ключа с выводом счетчика числа появлений данного ключа
добавление новой вершины в соответствии со значением ее ключа или увеличение счетчика числа появлений
построчный вывод дерева в наглядном виде с помощью обратно-симметричного обхода
вывод всех вершин в одну строку по порядку следования ключей с указанием для каждой вершины значения ее счетчика появлений
удаление вершины с заданным значением ключа
Выдает (в VS 2012) следующие ошибки:

Т. Е. он утв-ет что count не является однозначным и не определен
C++ для людей
std::cout
Часто встречающиеся ошибки стадии компиляции
Очень часто начинающие программисты впадают в суеверный ужас, когда видят, что компилятор нашел в тексте программы ошибку, но не понимают, в чем она заключается.
А если помножить этот факт на незнание английского языка («чего там ему не нравится. ») и слабое владение синтаксисом C++ («хм, а может, тут нужна точка с запятой…»), то проблема принимает масштаб катастрофы.
Тот факт, что компилятор в силу своих ограниченных возможностей изо всех сил старается объяснить, что конкретно неверно, не спасает ситуацию. Как быть, если гуглить неохота, а спросить не у кого?
В этом посте на правах копипаста с последующим переводом, дополнениями и исправлениями приведу описание наиболее распространенных сообщений об ошибках и предупреждений компилятора. Неприятность кроется в том факте, что разные компиляторы ругаются на одинаковые ошибки по-разному, а некоторые даже не замечают то, что другие принимают за ошибку. Все зависит от совести разработчиков компилятора, даты его выпуска, и др.
В качестве компилятора возьмем g++, который, в частности, может использоваться в среде Code::Blocks. Версия gcc (куда входит g++) для ОС Windows зовется MinGW. По ходу я буду давать аналоги ошибок из лексикона русскоязычной Microsoft Visual C++.
Итак, частые ошибки:
undeclared identifier
doy.cpp: In function ‘int main()’:
doy.cpp:25: ‘DayOfYear’ undeclared (first use this function)
doy.cpp:25: (Each undeclared identifier is reported only once for each function it appears in.)
doy.cpp:25: parse error before ‘;’ token
2) Смысл
Использован идентификатор DayOfYear , но компилятор не нашел его объявления. Он не знает, что такое DayOfYear .
- Вы забыли включить какой-то заголовочный файл ( #include. )
- Вы где-то ошиблись в написании идентификатора (при объявлении или использовании)
- Вы вообще забыли, что эту переменную надо объявить
Попытавшись скомпилировать это в Microsoft Visual C++, вы увидите:
error C2065: DayOfYear: необъявленный идентификатор
cout undeclared
xyz.cpp: In function ‘int main()’:
xyz.cpp:6: ‘cout’ undeclared (first use this function)
xyz.cpp:6: (Each undeclared identifier is reported only once for each function it appears in.)
2) Смысл
Суперклассика. Без комментариев.
- Вы забыли включить
- Вы забыли написать using namespace std;
jump to case label
switch.cpp: In function ‘int main()’:
switch.cpp:14: jump to case label
switch.cpp:11: crosses initialization of ‘int y’
2) Смысл
Смысл туманен
3) Когда бывает
Вы попытались объявить и инициализировать переменную (объект, указатель и т.п.) в метке case оператора выбора switch. Правилами C++ это запрещено.
В Microsoft Visual C++ эта ошибка зовется
error C2360: пропуск инициализации ‘y’ из-за метки ‘case’
Выход: заключите операторы этого case’а в фигурные скобки <>.
multi-line string / unterminated string
using namespace std;
вызовет бурную реакцию компилятора:
string.cpp:7:12: warning: multi-line string literals are deprecated
string.cpp: In function ‘int main()’:
string.cpp:7: ‘so’ undeclared (first use this function)
string.cpp:7: (Each undeclared identifier is reported only once for each function it appears in.)
string.cpp:7: parse error before ‘Mary’
string.cpp:8:28: warning: multi-line string literals are deprecated
string.cpp:8:28: missing terminating » character
string.cpp:7:12: possible start of unterminated string literal
2) Смысл
Компилятор думает, что мы хотим создать строковую константу с содержащимся в ней переносом строки, что-то типа
что не поддерживается языком. Также делается предположение о том, что мы, возможно, забыли поставить кавычки в конце первой строки. Собственно, так оно и есть.
3) Когда бывает
Когда не соблюдается правильное количество и положение кавычек в строковых литералах. Надо быть внимательнее.
Microsoft Visual C++ со свойственной ему детской непосредственностью, отметит, что нельзя делать переносы в строках и возмутится, где точка с запятой:
error C2001: newline в константе
error C2146: синтаксическая ошибка: отсутствие «;» перед идентификатором «cout»
comparison between signed and unsigned integer expressions
xyz.cpp: In function ‘int main()’:
xyz.cpp:54: warning: comparison between signed and unsigned integer expressions
2) Смысл
Это — предупреждение компилятора, которое говорит о том, что мы пытаемся сравнить (==, и т.д.) целочисленное выражение (может принимать положительные, отрицательные значения и 0) и беззнаковое целочисленное выражение (может быть только положительным, либо 0).
3) Когда бывает
Собственно, тогда и бывает. Напомню, что тип int по умолчанию знаковый, а некоторые функции (например, vector::size() ) возвращают unsigned int .
К примеру, следующий на первый взгляд безобидный код вызовет описываемое предупреждение:
Следует помнить, что в памяти знаковые и беззнаковые типы имеют разные внутренние представления, поэтому надо быть чертовски осторожными с указателями.
В Microsoft Visual C++ предупреждение выглядит так:
suggest parentheses around assignment used as truth value
xyz.cpp: In function `int main()’:
xyz.cpp:54: warning: suggest parentheses around assignment used as truth value
2) Смысл
Тоже классика. Компилятор предполагает (и в 99% случаев прав), что вы по ошибке включили в скобки в качестве условия для if/while/for вместо условного выражения выражение присваивания.
3) Когда бывает
Чаще всего — в if ‘ах, когда вместо «==» используется «=»
if (length = maxLength)
if (length == maxLength)
Заминка в том, что это не ошибка, т.к. в скомпилированной программе (если мы проигнорируем предупреждение) выражение присваивания (которое возвращает значение правого аргумента) во всех случаях, кроме тех, когда оно вернет 0 , будет преобразовано к true .
Избавляемся от ошибки «This function or variable may be unsafe» в Visual Studio
Время чтения: 5 минут

Компилятор в Visual Studio сильно отличается от привычных большинству программистов GCC или CLANG, из-за чего при написании кода на C или C++ очень часто возникают неожиданные проблемы в виде ошибки использования стандартных функций, например, scanf, fopen, sscanf и тому подобным. Студия предлагает заменять функции на безопасные (повезёт, если нужно просто добавить _s к функции с ошибкой, но нередко в этих функциях идёт иной набор аргументов, нежели в обычной программе). Если вы не готовы с этим мириться, то этот пост для вас!
Давайте для начала создадим обычный консольный проект в Visual Studio и напишем простенькую программу, которая запрашивает ввод двух чисел, вводит их и затем выводит на экран.
Попробовав выполнить сборку проекта, обнаружим те самые ошибки.
Чтобы Visual Studio не тратила ваши нервы, сделаем следующее:
1. Выберем пункт «Проект» в верхнем меню
2. В открывшемся списке щёлкнем по «Свойства название_проекта»


3. В появившемся окне выберем Свойства конфигурации , C/C++ , Препроцессор
4. В строке Определения препроцессора допишем в самый конец строку ;_CRT_SECURE_NO_WARNINGS



6. Попробуем заново выполнить сборку проекта:

Ошибки исчезли, сборка прошла успешно и программа прекрасно работает! Теперь можно писать код как обычно, не переживая о необычном поведении Visual Studio!

Программист, сооснователь programforyou.ru, в постоянном поиске новых задач и алгоритмов
Языки программирования: C, C++, Pascal, C#
Студент МГУ им. М.В. Ломоносова
А Вы знаете, что мы пишем программы на C, C++, C#, Pascal и Python?
Так что если Вам нужно написать программу на C/C++, C#, Pascal или Python — мы с радостью поможем с этим!
В том числе мы занимаемся репетиторством по информатике и программированию, а также готовим к ОГЭ и ЕГЭ!
Почему именно мы?
- Более 1800 выполненных заказов;
- Более 170 отзывов;
- Качественное решение
- Короткие сроки и привлекательные цены
- Различные акции и скидки
Как с нами связаться?
- группа Вконтакте: vk.com/programforyou
- наша почта: order@programforyou.ru

Programforyou — позвольте нам писать код для вас и вы получите качественное решение в короткие сроки по привлекательной цене!
Обзор средств ввода-вывода в C++
Приложение, написанное на любом языке программирования, должно взаимодействовать с окружающим миром. Иначе пользы от него не будет. Как правило, такое взаимодействие осуществляется посредством ввода-вывода информации на монитор или в файл. Правда, есть некоторое множество программ, которые не используют файловый или консольный ввод-вывод: это программы, осуществляющие низкоуровневое взаимодействие с аппаратной частью компьютера и периферией (ядро ОС, драйверы и пр.), но это уже экзотика.
В стандартном C++ существует два основных пути ввода-вывода информации: с помощью потоков, реализованных в STL (Standard Template Library) и посредством традиционной системы ввода-вывода, унаследованной от C. Если копнуть немного глубже, то окажется, что и потоки, и традиционная система ввода-вывода для осуществления необходимых действий используют вызовы операционной системы. И это правильно.
Дальнейшее изложение не претендует на полноту, но описывает основные принципы использования библиотек. Подробности использования можно посмотреть в многочисленной литературе по C++ и STL, в MSDN и пр.
Традиционный ввод-вывод
Для использования традиционного ввода-вывода в духе C, в программу необходимо включить заголовочный файл . (Разумеется, компилятор должен иметь доступ к соответствующей объектной библиотеке для правильной сборки исполняемого файла.)
Библиотека stdio предоставляет необходимый набор функций для ввода и вывода информации как в текстовом, так и в двоичном представлении. Следует отметить, что в отличие от классической C‑библиотеки, в современных библиотеках имеются более безопасные аналоги «классических» функций. Как правило, они имеют такое же имя, к которому добавлен суффикс _s. Рекомендуется использовать именно эти, безопасные функции.
Самая Первая Программа с использованием библиотеки stdio выглядит так:
При запуске консольного приложения неявно открываются три потока: stdin — для ввода с клавиатуры, stdout — для буферизованного вывода на монитор и stderr — для небуферизованного вывода на монитор сообщений об ошибках. Эти три символа определены посредством .
В stdio для консольного ввода-вывода предусмотрена отдельная группа функций. Однако эти функции, как правило, являются обёртками для аналогичных функций файлового ввода-вывода, для которых аргумент типа FILE задан по умолчанию.
Самая Первая Программа с использование файлового вывода из библиотеки stdio выглядит так:
Некоторые популярные функции из stdio:
Сущность FILE представляет собой структуру, в которой хранится вся информация для управления потоком ввода-вывода.
Файл открывается функцией fopen(), которой передаются два параметра. Первый параметр определяет имя файла. Второй — определяет режим открытия файла: чтение, запись, произвольный доступ и т.п., а также указание на то, как работать с данными: в текстовом или двоичном режиме. Подробности — см. в документации.
Пример использования stdio
Следует отметить, что существует еще одна библиотека, ориентированная исключительно на консольный ввод-вывод — .
Ввод-вывод с помощью потоков STL
Для использования объектно-ориентированного консольного ввода-вывода с помощью потоков (stream) STL в программу необходимо включить заголовочный файл , а для файлового ещё и . (Разумеется, компилятор должен иметь доступ к соответствующей объектной библиотеке для правильной сборки исполняемого файла.)
Самая Первая Программа с использованием потоков STL выглядит так:
При запуске консольного приложения неявно открываются четыре потока: сin — для ввода с клавиатуры, сout — для буферизованного вывода на монитор, сerr — для небуферизованного вывода на монитор сообщений об ошибках и clog — буферизованный аналог cerr. Эти четыре символа определены посредством .
Потоки cin, cout и cerr соответствуют потокам stdin, stdout и stderr соответственно.
Иерархия классов ввода-вывода STL достаточно сложна. Любители тонких ощущений могут найти её описание в литературе. Впрочем, остальных также не минует чаша сия, но только позже, когда потребуются знания чуть повыше того базового уровня, который описывается здесь.
Для ввода-вывода сначала необходимо создать поток — экземпляр соответствующего класса STL, а затем связать его с файлом. Для потока вывода используется класс ofstream, для потока ввода — ifstream, для потока ввода-вывода — fstream. В каждом из этих классов есть метод open(), который связывает поток с файлом. Проще говоря, открывает файл. Методу передаются два параметра: имя файла и режим открытия файла. Второй параметр представляет собой набор битовых флагов, определяющих режим открытия файла (чтение, запись и пр.) и способ работы с данными (текстовый или двоичный режим). Второй параметр опционален, т.е. имеет значение по умолчанию, соответствующее классу.
Вышеупомянутые классы имеют также конструкторы, позволяющие открыть файл сразу при создании потока. Параметры этих конструкторов полностью совпадают с параметрами метода open().
При ошибке открытия файла (в контексте логического выражения) поток получает значение false.
Файл закрывается методом close(). Этот метод также вызывается при разрушении экземпляров классов потоков.
Операции чтения и записи в поток, связанный с файлом, осуществляются либо с помощью операторов >, перегруженных для классов потоков ввода-вывода, либо с помощью любых других методов классов потоков ввода-вывода.
Некоторые наиболее употребляемые методы:
Пример использования потоков STL
Взаимодействие потокового и традиционного ввода-вывода
Апологеты C++ рекомендуют использовать для ввода-вывода только потоки STL и отказаться от использования традиционного ввода-вывода в духе C. Однако, ничто не мешает, по крайней мере пока, использовать традиционную систему ввода-вывода. Более того, предусмотрена специальная функция для синхронизации ввода-вывода, выполненного посредством потоков и посредством старых функций.
Заключение
Какой механизм использовать — вопрос предпочтений программиста, если работодателем явно не предписано использование конкретного механизма. В любом случае для физического ввода-вывода используются вызовы операционной системы. Всё остальное — обёртка, набор более или менее удобных функций или классов для взаимодействия с ОС.
Использование механизма потоков считается более безопасным. Но, как известно, плохую программу можно написать на любом языке программирования. Это также относится и к использованию библиотек. Автор статьи: Череп.
Неоднозначный Синтаксис
Почему последние две строки в основной функции перед закрывающей скобкой дают ошибку? Почему выражение MYINT() трактуется по-разному в разных контекстах? Любая стандартная ссылка будет полезна.
5 Ответов
MYINT() может, в зависимости от контекста, интерпретироваться как выражение типа MYINT или спецификатор типа функции, не принимающий аргументов и возвращающий MYINT . В некоторых ситуациях, когда допустимо выражение или спецификатор типа, это дает неоднозначность; это разрешается путем интерпретации его как спецификатора типа, если это возможно ( EDIT: C++03 8.2/2, если требуется стандартная ссылка).
sizeof может принимать либо выражение, либо заключенный в скобки спецификатор типа, как это аргумент, давая эту двусмысленность. Таким образом, здесь MYINT() интерпретируется как спецификатор типа; затем вы получаете ошибку, так как sizeof не может быть применен к типу функции.
EDIT: вы можете исправить ошибку, удалив скобки, чтобы она интерпретировалась как выражение ( sizeof MYINT() ), добавив дополнительные скобки, чтобы она не была допустимым спецификатором типа ( sizeof((MYINT())) ), или изменив ее на правильный тип ( sizeof(MYINT) ).
cout является однозначным, поэтому ошибки быть не должно, и действительно нет на моем компиляторе. Что такое ошибка, и что такое ваш компилятор?
Если ваш MINTINT — это typedef int MYINT , то MYINT() -это не функция, а int() , которая является инициализацией по умолчанию, равнозначной int y = 0 или int y = int(0) .
Ваша вторая строка, т. е. cout компилируется правильно для меня с g++ -Wall -ansi -pedantic по той же причине.
Но g++ будет жаловаться на sizeof со следующей ошибкой error: invalid application of «sizeof» to a function type , потому что он интерпретирует MYINT() как «a call to a default constructor for int» ( EDIT : это неверно) «a function type returning MYINT which is not allowed» ( EDIT : это правильный ответ, см. Майка). Но это не имеет ничего общего с typedef .
Редактировать (снова)
Как сказано в комментарии, строки cout не работают для вас, это потому, что вы, вероятно, забыли include .
Edit Посмотрите также ответ Майка Сеймура для объяснения двусмысленности с sizeof .
Почему последние две строки в основной функции перед закрывающей скобкой дают ошибку?
cout не работает, потому что cout не определен. Как только вы сделаете #include и using std::cout , он будет работать нормально.
sizeof(MYINT()) действительно не работает, но sizeof(int()) тоже не работает, так что этого следует ожидать. sizeof(MYINT) будет работать просто отлично.
Почему выражение MYINT() трактуется по-разному в разных контекстах?
Это не. В каждом случае MYINT() ведет себя точно так же, как int() .
Я не вижу никакой ошибки для строки cout . Однако я вижу invalid application of ‘sizeof’ to a function type для строки cout . Проблема заключается в () вокруг MYINT() . Стандарт C++ говорит Это О sizeof и о том, как он анализируется:
Существует неоднозначность синтаксического анализа между sizeof unary-expression и sizeof ( type-id ) . Он решается с помощью более длинного матча. Он анализирует sizeof (MYINT()) как sizeof ( type-id ) , MYINT() -это тип функции, и таким образом вы видите ошибку.
Похожие вопросы:
Как исправить эту ошибку? ошибка C2668: ‘std::_Tree :: end’: неоднозначный вызов перегруженной функции Мой код выглядит так: typedef map my_map_t; my_map_t.
Я создаю новый проект, и я добавляю существующую ссылку на проект и вызываю один класс из существующего. Я получаю ниже ошибку — — — Ошибка c2872: неоднозначный символ
Я читаю следующий документ о функциональных зависимостях. На странице 5 он описывает неоднозначный тип: Во-первых, пустая функция имеет неоднозначный тип: empty :: Collects e ce ⇒ ce. Под.
Предположим, у меня есть такой запрос select id, company_id, name, type, number from people as p inner join company c on c.id = p.company_id limit 10 и здесь обе таблицы имеют столбец name, и name.
У меня есть внутреннее соединение двух таблиц и дисплей. Я попробовал приведенный ниже код. Но он генерирует на ошибке неоднозначный столбец site_name’ SELECT site_name, Mains_Run_Hrs.
Неоднозначный grammar определяется как, Неоднозначный grammar-это контекстно-свободный grammar, для которого существует строка, которая может иметь более одного крайнего левого вывода или дерева.
Скажи, что у меня есть: @Given(first name is $firstName) @Given(first name is $firstName and last name is $lastName) Следующий шаг будет помечен как неоднозначный: Given first name is John and last.
Я предоставлю этих двух конструкторов. BigUnsigned(int value) :BigUnsigned(static_cast (value)) < >BigUnsigned(unsigned long long value); Проблема в том, что вызов.
То, что я часто вижу в интернете, когда тема переворачивается, — это такой синтаксис *(_WORD *)(a1 + 6) = *(_WORD *)(a2 + 2); Я думаю, что этот код от плагина IDA (верно?), но я не могу этого понять.
NOTICE: этот вопрос не о Java do not have pointers В языке C код identifier1 * identifier2 неоднозначен для двух возможных значений: Если identifier1 является типом, то это может быть объявление.
Cout не является однозначным ошибка
Снова про ввод/вывод в C++
Хочу продолжить тему скорости ввода/вывода в C++, которую когда-то начал товарищ freopen. freopen сравнивал производительность двух способов ввода/вывода в C++: унаследованной от C библиотеки stdio ( ) и более новой библиотеки iostreams ( /…). Однако в этих тестах не было учтено, что iostreams можно значительно ускорить, включив некоторые оптимизации. Об их существовании уже неоднократно упоминалось на Codeforces (раз, два, три). Сейчас я написал софт, который сравнивает производительность stdio и iostreams на стандартном вводе/выводе с учётом этого.
UPD1: Добавлена информация про _CRT_DISABLE_PERFCRIT_LOCKS .
UPD2: Для полноты картины добавлены вызовы printf() / scanf() на строках.
Что это за оптимизации?
Первая состоит в том, что в начале программы, перед каким-либо вводом/выводом, можно вставить строчку
Эта команда отключает синхронизацию iostreams с stdio (описание). По умолчанию она включена, то есть, iostreams и stdio можно использовать вместе на одном и том же потоке, перемежая их вызовы. После отключения синхронизации так делать больше нельзя, однако за счёт этого iostreams может работать быстрее.
Вторая оптимизация заключается в том, что для cin можно выключить привязку к cout :
По умолчанию cin привязан к cout , что означает, что перед каждой операцией над cin сначала сбрасывается буфер cout (описание). Отключение этой функции опять-таки позволяет iostreams работать быстрее. С этой оптимизацией надо быть внимательным в интерактивных задачах: либо не использовать её, либо не забывать явный flush .
Отмечу ещё, что на производительность iostreams негативно влияет частое использование endl , поскольку endl не только выводит символ новой строки, но и сбрасывает буфер потока (описание). Вместо endl можно просто выводить ‘n’ или «n» .
Какие тесты включены в программу?
Я постарался сымитировать наиболее типичные ситуации, возникающие при решении задач.
- Ввод/вывод int с помощью stdio, iostreams и, для сравнения, самопальных функций
- Ввод/вывод double
- Посимвольный ввод/вывод
- Ввод/вывод строк: как с char * , так и с std::string
Какие тесты не включены в программу?
- long long — полагаю, результат будет коррелировать с int
- Преобразование int и запись результата в собственный буфер достаточно большого размера, а затем прямой вывод буфера с помощью fwrite() / cout.write() (и аналогичное решение для ввода)
- Экзотический способ посимвольного ввода/вывода: cin.rdbuf()->sgetc() и cout.rdbuf()->sputc()
- Какие-либо манипуляции с размером буфера потоков (похоже, что в GCC iostreams для стандартных потоков игнорирует пользовательские установки насчёт этого). Это направление ещё можно исследовать потом.
Как это запустить у себя?
Надо скомпилировать программу, не забыв включить оптимизацию ( -O2 /Release), и запустить её с тем же рабочим каталогом, где она и находится. Если при запуске в Windows появляется сообщение Access denied, то может помочь запуск программы с повышенными правами. Программе потребуется пара сотен мегабайтов свободного места в каталоге для временных файлов.
Дополнительные замечания
- Почему нужно для каждого теста создавать новый процесс?
Из-за ios_base::sync_with_stdio(false) , который препятствует поочерёдному тестированию stdio и iostreams, а также (теоретически) мешает использовать freopen() , чтобы перенаправлять cin / cout .
- Зачем удалять файл от предыдущего запуска перед каждым тестом?
Чтобы все запуски были в равных условиях. Хотя, это несколько спорный вопрос. Может, лучше не удалять, а переписывать?
- Почему время измеряет запускаемый, а не запускающий процесс?
Чтобы исключить время запуска/завершения процесса.
- Почему бы вместо clock() не использовать более точные вызовы, например, getrusage() ?
Это можно. Но сначала мне надо понять, как это делать в Windows 🙂
Результаты
Запускал на компьютере с Pentium 4, так что время может показаться несколько большим.
Здесь всё очевидно: stdio значительно превосходит по скорости iostreams. Примечательно, что на int printf() / scanf() быстрее даже самописных функций (однако см. дополнение ниже). Ввод/вывод строк с помощью puts() / gets() быстрее, чем с помощью printf() / scanf() — ну, это и понятно. Запись std::string занимает столько же, сколько и запись char * , а вот чтение в std::string медленнее — наверняка из-за необходимости динамически выделять память.
А здесь всё уже не так однозначно. Неожиданно оказывается, что iostreams на 20-30% быстрее stdio на int . Правда, самописные функции значительно обгоняют и то, и то. С double наоборот: iostreams заметно тормозит. Посимвольный ввод/вывод с putchar() / getchar() работает в 2-3 раза быстрее cout / cin . Ввод/вывод строк отличается не так сильно, но stdio и тут быстрее. На строках puts() / gets() также быстрее, чем printf() / scanf() . std::string , как и в предыдущем случае, работает одинаково с char * на выводе, однако медленнее на вводе.
Какие делать выводы и что использовать, пусть каждый решает сам. В комментариях приветствуется флейм конструктивное обсуждение.
Дополнение
В Visual C++ есть способ значительно ускорить базовые операции с потоками stdio, отключив блокировку потоков для функций getchar() , putchar() и некоторых других. Для этого надо перед всеми #include вставить строчку
(описание). Это сработает только при выполнении следующих дополнительных условий:
- Программа статически компонуется со стандартной библиотекой ( /MT ; на Codeforces, похоже, это так)
- Программа включает , но не включает ни , ни какой-либо файл из библиотеки iostreams ( /…)
Вместо всей этой магии можно также просто использовать _putchar_nolock() / _getchar_nolock() вместо putchar() / getchar() . В Linux тоже есть похожие функции: ссылка.
С этой оптимизацией посимвольный ввод/вывод ускоряется в восемь-девять (!) раз, а вместе с ним и вручную написанные функции ввода/вывода int :
В MinGW такое поведение включено по умолчанию и не имеет вышеописанных ограничений.