Часть 2. Я начинающий, подскажите как...(Все вопросы начинающих!!!)
ListBox1->Columns=3;
каким образом записать строку в второй и третий столбцы?
#include "stdafx.h"
#include <fstream>
#include <iostream>
#include <stdlib.h>
using namespace std;
void error (const char * message)
{
cerr<<'\n'<<message<<'\n';
exit(1);
}
int main (int argc, char *argv[]){
char fileName[32];
char buf[64];
ifstream in;
ofstream out;
in.open("C:\\1.txt");
if(!in.good()) error("can't open file for reading.");
in.getline(buf, sizeof(buf));
for(int i=2; i <= 5; i++){
sprintf(fileName,"c:\\%d.txt",i);
out.open(fileName);
if(!out.good()) error("can't open file for writing.");
out << "hi " << buf << endl;
out.close();
system (fileName,"notepad c:\\%d.txt",i);
}
in.close();
return 0;
}
эта прога должна копирывать файл 1.txt 4 раза и каждый новый файл на зывать по разному и после создания открывать его. Подскажите в чём проблема.
Как правильно написать system (); в моём коде.
Образно говоря, ключевое слово typedef позволяет вводить синонимы имещихся типов данных. Например, строка
x = 10;
Аналогично со структурами. Структура объвляется так:
ЗЫ: особо отмечу, что для создания "управляемых" структур следует объявлять их с ключевым словом ref
Читайте здесь описание функции system (и вообще - используйте сначала справочник функций перед тем как задавать по ним вопросы).
На той странице смотрим прототип функции:
Подумайте - сколько аргументов и какого типа аргументы должна иметь функция при корректном вызове, и сравните с тем как она вызывается у вас (должно стать понятно что не так):
Не прав.
Без лишних слов: формат [FONT="Courier New"]typedef struct[/FONT] используется в языке С. Наиболее часто применяется в конструкциях вида:
typedef struct node_t
{
int data;
struct node_t* prev;
struct node_t* next;
} node_t;
int main()
{
node_t node1, node2, node3;
node1.data = 1;
node1.prev = NULL;
node1.next = &node2;
node2.data = 2;
node2.prev = &node1;
node2.next = &node3;
node3.data = 3;
node3.prev = &node2;
node3.next = NULL;
printf( "node1.data = %d, node1.data = %d, node1.data = %d\n",
node1.data, node2.data, node3.data );
printf( "node1.next->data = %d, node3.prev->data = %d\n",
node1.next->data, node3.prev->data );
return 0;
}
В языке С++ это теряет смысл. Т.е. думаю, понятно. А вообще, K&R - в руки. Так же, описано в стандартах 89, 95 и 99 года.
Вы пытаетесь вызывать данную функцию аналогично sprintf, ожидая что в ней будут произведены необходимые подстановки, что неправильно, т.к. этого в функции system не предусмотрено. Аргументом функции system должен быть char-овский массив, содержащий уже сформированный текст команды, которую нужно выполнить. В вашем случае, я так полагаю, должно быть что-то вроде такого:
sprintf(cmdText, /* здесь поместите нужные вам спецификацию и данные ввода*/);
system(cmdText);
З.Ы: int *x;
x и &x имеют разные значения, неужели потому, что x - адрес указателя, а &x -адрес на указатель ?:)
Если на игровом форуме искать, то да, конечно. А если у гугля спросить, то будет информация несколько иного плана. Прямо с первой ссылки.
З.Ы: int *x;
x и &x имеют разные значения, неужели потому, что x - адрес указателя, а &x -адрес на указатель ?:)
А на этот вопрос, вам прекрасно ответит практически любой учебник C\C++. Добавлю, что С++ не оперирует понятием адрес.
P.S. Это, конечно, топик для начинающих. Но именно к начинающим, в первую очередь направлено послание RTFM.
объявление структур typedef struct { } st; и struct st{};
последний вариант позволяет создавать ссылки на себя самих(для рекурсии) а вот какое принципиальное отличие в спецификаторе typedef кроме как расположения его после фигурак - не врубаюсь хоть убейте)
Купи себе книжку Шилдта Справочник программиста С\С++, тогда такие вопросы отпадут оч. быстро).
про typedef:
typedef позволяет определить новое имя для уже существующего типа данных:
в C++ его обычно применяют, когда определение типа становиться слишком длинным(например в работе с STL).
как пример...
есть у меня тип vector<Book>::interator, но в коде мне лень лишний раз так писать)) или хочется большей читабельности кода.
поэтому я могу сделать так:
typedef vector<Book>::interator page;
И дальше в коде вместо vector<Book>::iterator писать просто page. Надеюсь понятно написал.
Если я вас правильно понял и вам нужна выдача скан-кода нажатой клавиши на экран, то можно, например, так:
если быть точным то вот так
по другому не работало.
а можно как нибудь с cin.get'ом?
заранее благодарен
если числовой код, то:
#include <conio.h>
using namespace std;
void main()
{
int a = int(_getch());
cout << "a= " << a << endl;
_getch();
}
вполне работает=)
или:
это если char надо получить
п.с.
поэтому юзаю _getch() =)
if(a == 0 || a == 0xE0) a = _getch();
если _getch() вернула 0 или 0xE0, то была нажата системная клавиша и для получения её кода надо вызвать _getch() ещё раз))
опытным путём получено, что код Esc равен 27=)
п.с. тесты показали...
для того, чтобы обработать нажатие Esc достаточно вставить проверку if(a == 27), т.е. нету возврата 0 или 0xE0
*имхо удобно считывать код в int, проводить проверку, а потом, если надо, переводить в char
для обработки нажатий F1-F10 нужно использовать проверку if(a == 0), т.к. сначала они возвращают 0, через _getch() и чтобы получить какая из них нажата, нужно ещё раз вызвать _getch(), а потом уже свой код.
0xE0 т.е. 224 в десятичной системе возвращается при нажатии на F11,F12,Insert, Delete и т.п., при повторном вызове _getch() выдаст соотв. код конкретной клавиши.
вот код, поиграйся вообщем)
#include <conio.h>
using namespace std;
void main()
{
int a = _getch();
while(1)
{
if(a == 27)
{
cout << "Down " << char(a) << ", code: " << a << endl;
cout << "The End\n";
_getch();
return;
}
cout << "Down " << char(a) << ", code: " << a << endl;
a = _getch();
}
}
если _getch() вернула 0 или 0xE0, то была нажата системная клавиша и для получения её кода надо вызвать _getch() ещё раз))
опытным путём получено, что код Esc равен 27=)
п.с. тесты показали...
для того, чтобы обработать нажатие Esc достаточно вставить проверку if(a == 27), т.е. нету возврата 0 или 0xE0
*имхо удобно считывать код в int, проводить проверку, а потом, если надо, переводить в char
для обработки нажатий F1-F10 нужно использовать проверку if(a == 0), т.к. сначала они возвращают 0, через _getch() и чтобы получить какая из них нажата, нужно ещё раз вызвать _getch(), а потом уже свой код.
0xE0 т.е. 224 в десятичной системе возвращается при нажатии на F11,F12,Insert, Delete и т.п., при повторном вызове _getch() выдаст соотв. код конкретной клавиши.
вот код, поиграйся вообщем)
я конечно поигрался с этим делом. но мне надо не много другое.
допустим простейшая прога:
{
int a;
cout << "Загадай число.\n";
cin >> a;
. . .
. . .
}
вас просят что-то ввести. и как сделать так чтобы он считывал клавишу в момент ввода числа или строки. т.е если во время ввода числа вы ничего не напишите а нажмете esc - он вам выдает что-то вроде отмена ввода. как так сделать?
допустим простейшая прога:
{
int a;
cout << "Загадай число.\n";
cin >> a;
. . .
. . .
}
вас просят что-то ввести. и как сделать так чтобы он считывал клавишу в момент ввода числа или строки. т.е если во время ввода числа вы ничего не напишите а нажмете esc - он вам выдает что-то вроде отмена ввода. как так сделать?
примерно так(заюзал string, т.к. лень было думать над длиной числа и выделяемой для него строки соотв.):
#include <conio.h>
#include <string>
using namespace std;
void main()
{
char a = _getch();
string s;
while(1)
{
if(a == 27)
{
cout << "Down " << char(a) << ", code: " << a << endl;
cout << "end...\n";
_getch();
break;
}
cout << "Down " << char(a) << ", code: " << a << endl;
s += a;
a = _getch();
}
cout << atoi(s.c_str()) << endl;
_getch();
}
тут нажатие Esc служит завершением ввода=)
При работе с указателями возникли проблемки в понимании языка:
1. Почему отличаются
2. Почему участки кода
cout << *pointer++;
в котором теоретически выполняется pointer++, а затем возвращается значение, находящееся по адресу и
cout<<*pointer;
pointer++;
}
в котором сначала вывод, а зачем уже увеличение адреса, идентичны?
При работе с указателями возникли проблемки в понимании языка:
1. Почему отличаются
всё дело в том, что когда ты используешь постфиксное инкрементирование, т.е. p++, что инкрементирование происходит после того, как указатель будет разыменован и содержимое памяти, по хранящемуся там адресу, будет выведено на экран(в общем случае после того, как будут произведены какие либо внешние действия над инкрементируемым объектом).
если же ты хочешь, чтобы сначала изменилось значение указателя, то используй префиксное инкрементирование, т.е. ++p
* оператор += работает в твоём случае как префиксное инкрементирование.
думаю из этого тебе будет легко понять, почему циклы эквивалентны.
эх... где то в локалке нашего универа видел статейку про инкрементированию и декрементированию, но прочитав себе не сохранил=(
При работе с указателями возникли проблемки в понимании языка...
Добавить можно, разве что наглядные примеры:
*(++ptr); // префиксная форма: инкремент, потом получаем значение
Для разминки: попробуй сказать, что происходит в следующей конструкции:
...
while (*pb++ = *pa++);
а насчет второго вопроса, то там в коде:
cout << *pointer++;
как раз ++ должен выполняться раньше, чем *, т.к. приоритет операций одинаков, но ++ находится справа (ассоциативность).
Небольшой кусочек кода для понимания работы с указателями:
using namespace std;
void main()
{
int x[] = { 1,2,3,4,5,0 };
int *p1 = x;
while (*p1)
cout << *p1++ << " ";
cout << endl;
int *p2 = x;
while (*p2) {
cout << *p2 << " ";
p2++;
}
cout << endl;
int *p3 = x;
while (*p3)
cout << *++p3 << " ";
cout << endl;
int *p4 = x;
while (*p4) {
*p4++;
cout << *p4 << " ";
}
cout << endl;
int *p5 = x;
while (*p5)
cout << *(p5+=1) << " ";
cout << endl;
}
грубо говоря в префиксной форме сначала выполниться инкрементирование, а потом другие операции,а в постфиксной сначала операции, а потом инкрементирование.
вот примерчик с обычными числами:
#include <conio.h>
using namespace std;
void main()
{
int i = 5;
int a = (++i) + (++i);
i = 5;
int b = (i++) + (i++);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "i = " << i << endl;
_getch();
}
b = 10
i = 7
п.с. а вообще имхо использование конструкций типа *(p++) или *(++p) некрасиво и снижат понимаемость кода. я придпочитаю разыменовывание отдельно, инкрементирование отдельно делать.
или использовать смещение в выводе: *(p + i)//где i - целое число
...
while (*pb++ = *pa++);
Здесь производится разыменование pa и pb, потом компилятор пытается присвоить друг другу числа, это приводит к необработанному исключению.
Norgat
Спасибо, теперь первый мой вопрос отпадает, это понял.
Насчет второго еще не все ясно. А именно касательно этого кода:
Я читаю книгу "ООП в c++" Лафоре и он как раз рассматривает этот случай:
Как компилятор интерпретирует *p++: как *(p++), что нам и нужно или как (*p)++? Здесь * и ++ имеют одинаковый приоритет. Операции одинакового приоритета различаются ассоциативностью. Унарные операции * и ++ имеют правую ассоциативность, таким образом, сначала увеличивается указатель, а затем к результату применяется операция разыменования.
т.е. он имеет ввиду, что сначал постфиксная операция ++, а потом префиксная *. это и не понятно..
...
while (*pb++ = *pa++);
Здесь производится разыменование pa и pb, потом компилятор пытается присвоить друг другу числа, это приводит к необработанному исключению.
Ух ты. :D Нихрена себе. Я (да и не только я) всегда был уверен, что это простое копирование C-style строки. Чем и пользовался лет 15...
Дык, переменные не инициализированные.
Ну, сверкани.
using namespace std;
int main()
{
char* pa = "f\0";
char* pb = "d\0";
while (*pb++ = *pa++);
return 0;
}
незнаю уж какого там года Лафоре твой... но сейчас специально поскал описание опереций ++ и -- в Павловской издания 2009 года.
там на стр. 33 чёрным по белому написано тоже самое, что и я тебе написал)
да и работа кода говорит сама за себя;)
п.с. а смысл браться за ООП, если у тебя траблы с указателями? может стоит сначала прочитать какой-нибудь классический учебник по С/С++? типа Подбельского или Павловской?
using namespace std;
int main()
{
char* pa = "f\0";
char* pb = "d\0";
while (*pb++ = *pa++);
return 0;
}
Оба указателся в этом примере указывают на константные строки, поэтому при попытке присваивания *pb=... происходит исключение.
Нужно сделать что-то вроде:
и всё работает.
незнаю уж какого там года Лафоре твой... но сейчас специально поскал описание опереций ++ и -- в Павловской издания 2009 года.
Вы полагаете, что поведение данных операторов меняется ежегодно?
может стоит сначала прочитать какой-нибудь классический учебник по С/С++? типа Подбельского или Павловской?
Да уж, Подбельский и Павловская - воистину классика жанра. Не чета всяким Лафоре, Майерсам, и прочим Страуструпам.
код:
mdll.h
#define _MDLL_H_
#include <iostream>
#include <stdio.h>
#include <windows.h>
using std::cout;
using std::endl;
extern "C" __declspec(dllexport) void NumberList();
extern "C" __declspec(dllexport) void LetterList();
#endif
mdll.cpp
#define MAXMODULE 50
char module[MAXMODULE];
extern "C" __declspec(dllexport) void NumberList() {
GetModuleFileName(NULL, (LPWCH)module, MAXMODULE);
cout << "This function eas called from " << module << endl;
cout << "NumberList: ";
for(int i = 0; i < 10; i++)
cout << i+1 << " ";
cout << endl << endl;
}
extern "C" __declspec(dllexport) void LetterList() {
GetModuleFileName(NULL, (LPWCH)module, MAXMODULE);
cout << "This function eas called from " << module << endl;
cout << "NumberList: ";
for(int i = 0; i < 26; i++)
cout << char(i+97) << " ";
cout << endl;
}
код в проекте, где используется эта библиотека
dllprj.h
#define _DLLPRJ_H_
#pragma comment(lib, "mdll.lib")
#include "mdll.h"
#endif
dllprj.cpp
void main() {
NumberList();
LetterList();
}
ошибки:
1>MSVCRTD.lib(crtexew.obj) : error LNK2019: unresolved external symbol _WinMain@16 referenced in function ___tmainCRTStartup
1>E:\...\Visual Studio 2008\Projects\dllprj\Debug\dllprj.exe : fatal error LNK1120: 1 unresolved externals
там что то с функцией main? помогите понять.
dllprj.cpp
#include "dllprj.h"
void main() {
NumberList();
LetterList();
}
typedef void (WINAPI *cfunc)();
cfunc NumberList();
cfunc LetterList();
#define MAXMODULE 50
void main() {
HINSTANCE hLib = LoadLibrary((LPCWSTR)"mdll.dll");
if(hLib == NULL) {
cout << "Unabte to load DLL" << endl;
getch();
return;
}
char mod[MAXMODULE];
GetModuleFileName((HMODULE)hLib, (LPWCH)mod, MAXMODULE);
cout << "Module loaded: " << mod << endl;
NumberList = (cfunc)GetProcAddress(hLib, "NumberList");
LetterList = (cfunc)GetProcAddress(hLib, "LetterList");
if(NumberList == NULL || LetterList == NULL) {
cout << "Unable to load function(s)" << endl;
getch();
return;
}
NumberList();
LetterList();
FreeLibrary(hLib);
getch();
}
ошибки:
1>e:\...\visual studio 2008\projects\dlprj\dlprj.cpp(5) : error C2556: 'cfunc NumberList(void)' : overloaded function differs only by return type from 'void NumberList(void)'
1> e:\...\visual studio 2008\projects\dlprj\mdll.h(11) : see declaration of 'NumberList'
1>e:\...\visual studio 2008\projects\dlprj\dlprj.cpp(5) : error C2373: 'NumberList' : redefinition; different type modifiers
1> e:\...\visual studio 2008\projects\dlprj\mdll.h(11) : see declaration of 'NumberList'
1>e:\...\visual studio 2008\projects\dlprj\dlprj.cpp(6) : error C2556: 'cfunc LetterList(void)' : overloaded function differs only by return type from 'void LetterList(void)'
1> e:\...\visual studio 2008\projects\dlprj\mdll.h(12) : see declaration of 'LetterList'
1>e:\...\visual studio 2008\projects\dlprj\dlprj.cpp(6) : error C2373: 'LetterList' : redefinition; different type modifiers
1> e:\...\visual studio 2008\projects\dlprj\mdll.h(12) : see declaration of 'LetterList'
1>e:\...\visual studio 2008\projects\dlprj\dlprj.cpp(14) : error C3861: 'getch': identifier not found
1>e:\...\visual studio 2008\projects\dlprj\dlprj.cpp(27) : error C3861: 'getch': identifier not found
1>e:\...\visual studio 2008\projects\dlprj\dlprj.cpp(30) : error C3861: 'NumberList': identifier not found
1>e:\...\visual studio 2008\projects\dlprj\dlprj.cpp(31) : error C3861: 'LetterList': identifier not found
1>e:\...\visual studio 2008\projects\dlprj\dlprj.cpp(33) : error C3861: 'getch': identifier not found
чувствую что глупость какая-то, но найти немогу..