Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > На пути познания


Автор: Vendigo 13.1.2006, 18:28
Чем спамить в разных темах решил создать свою, где и буду озвучивать все те вопросы которые возникают у меня при изучении этого языка.
Добавлено @ 18:34
Для начала сугубо конкретный вопрос. Помогите найти ошибку.

У меня есть структура:
Код

struct Data_list
    {
    char name[64];        
    int birthday;        
    char addres[64];      
    int telephone;        
    char nik[32];        
    char sex;            
    char company[32];     
    char note[1024];     
    };

И функция которая вводит данные в структуру:
Код

void input()
{
    int a = 1;
    do
        {
        int i;
        for(i = 0; i < Size; i++)
            if(Data_book[i].name[0] == '\0') break;    // Ищем пустую строку
        if(i == Size)                                                   // Если цикл прошел весь
            {                                                               // пустых строк нет
            cout << "no memory\n";
            return;
            }

        cout << "\ninput name: ";         //Вводим данные
        gets(Data_book[i].name);
        cout << "\ninput addres: ";
        gets(Data_book[i].addres);
        cout << "\ninput birthday(19791001): ";
        cin >> Data_book[i].birthday ;
        cout << "\ninput telephone: ";
        cin >> Data_book[i].telephone;

        cout << "\nREPET? (Yes-1/No-0)";             // Запрос повторного ввода
        cin >> a;
        } while(a);                                                 //Повтор ввода при необходимости
}

Функция gets() работает неправильно, срабатывает только второй вызов этой функции. Если использовать оператор cin >> то все работает нормально.

Насколько я понимаю в функцию gets() в качестве параметра нужно передать имя символьного массива (эдакую строку) без индекса. Имя символьного массива без индекса в свою очередь трактуется в С++ как указатель на его первый [0] элемент.

Разве член структуры Data_book[i].name не соответствует этому определению?

Автор: Partizan 13.1.2006, 18:47
Во первых какую размерность имеет Data_book???
упс smile

Автор: _hunter 13.1.2006, 18:52
в смысле "рабатывает только второй вызов этой функции"?
в чем это выражается?

Автор: Void 13.1.2006, 19:19
Проблема проявляется из-за того, что оператор >> оставляет в потоке '\n', gets читает его и тут же завершается. Можно убедиться на следующем примере:
Код
#include <iostream>
#include <cstdio>

int main() {
    char buf[64];
    std::cin >> buf;
    std::gets(buf);
    std::cout << buf;
}

Лечение простое:
Код
std::cin >> buf >> std::ws;

Манипулятор ws поскипает пробелы и служебные символы.

Да, и еще: мешать потоки и C stdio - плохая затея. Вместо gets воспользуйся лучше cin.getline:
Код
cin.getline(Databook[i].name, sizeof(Databook[i].name));

Автор: bilbobagginz 13.1.2006, 20:38
и вообще КТО ЭТОТ Data_book ?! smile
где он объявлен ? smile

какого черту далась тебе эта функция в инструкции которой написано:
НЕ ИСПОЛЬЗУЙТЕ ЭТУ ФУНКЦИЮ.

?

Автор: blackofe 13.1.2006, 20:44
Цитата(bilbobagginz @ 13.1.2006, 20:38)
какого черту далась тебе эта функция в инструкции которой написано:
НЕ ИСПОЛЬЗУЙТЕ ЭТУ ФУНКЦИЮ.

оффтоп, но вспомнилось просто из spaceballs: там в звездолете кнопка большая и красная: "аварийная остановка. ни в коем случае не нажимать!" smile

Автор: Vendigo 13.1.2006, 21:25
Привет!
Спасибо за оперативность. Я понял... что я почти ничего не понял. Я еще не знаю что такое потоки.
Разбирался с структурами и составил эту учебную программку.

2 bilbobagginz Вот Data_book:
Код

const int Size = 256;
Data_list Data_book[Size];

Цитата(bilbobagginz @ 13.1.2006, 20:38 Найти цитируемый пост)

какого черту далась тебе эта функция в инструкции которой написано:
НЕ ИСПОЛЬЗУЙТЕ ЭТУ ФУНКЦИЮ.


Ты имеешь ввиду gets()? Не знал, что ее нельзя использовать smile


Автор: Void 13.1.2006, 21:28
Цитата(Vendigo @ 13.1.2006, 23:25 Найти цитируемый пост)
Я еще не знаю что такое потоки.

cin/cout - это стандартные потоки ввода-вывода.

Цитата(Vendigo @ 13.1.2006, 23:25 Найти цитируемый пост)
Ты имеешь ввиду gets()? Не знал, что ее нельзя использовать

Эта функция не проверяет, не выходят ли введенные данные за пределы выделенного буфера. Поэтому ее категорически не рекомендуется использовать. Вместо нее следует применять fgets или istream::getline.

Автор: blackofe 13.1.2006, 22:22
Цитата(Void @ 13.1.2006, 21:28)
Эта функция не проверяет, не выходят ли введенные данные за пределы выделенного буфера. Поэтому ее категорически не рекомендуется использовать. Вместо нее следует применять fgets или istream::getline.

я со всем согласен, но напрашиваются параллели. ведь char a[20] тоже нельзя использовать - потому что легко можно выйти за пределы строки. и какой-нибудь strcat() тоже нельзя использовать. а указатели совершенно не рекомендуется использовать - мало ли что с их помощью можно натворить! а уж new - просто под замок - потому что сплошь и рядом забывают вызывать ответный delete.

вывод: не программируйте, други мои. это опасно для жизни.

ни в коем случае не наезд и не попытка растления неопытных. но согласитесь, логика таки в моих словах есть. smile

Автор: Void 13.1.2006, 22:28
Цитата(blackofe @ 14.1.2006, 00:22 Найти цитируемый пост)
вывод: не программируйте, други мои. это опасно для жизни.

Из вышесказанного, ИМХО, следует несколько иной вывод: не программируйте на C++ - это опасно для жизни. smile
Прошу не воспринимать как призыв к холивару - просто настроение у меня такое smile

Цитата(blackofe @ 14.1.2006, 00:22 Найти цитируемый пост)
логика таки в моих словах есть.

Дао, высказанное словами, не есть Дао. smile

Так что, действительно, давайте не будем растлевать малолетних smile

Автор: blackofe 13.1.2006, 22:42
Цитата(Void @ 13.1.2006, 22:28)
Так что, действительно, давайте не будем растлевать малолетних smile

deal smile

а настроение, действительно, того.. только клопов давить под такое настроение smile

Автор: dronzo 13.1.2006, 22:59
Цитата(Void @ 13.1.2006, 22:28)
Из вышесказанного, ИМХО, следует несколько иной вывод: не программируйте на C++ - это опасно для жизни. smile
Прошу не воспринимать как призыв к холивару - просто настроение у меня такое.

Void, Это не холивар, это ты Страуструпа цитируешь : "Программируя на С вы легко можете прострелить себе ногу, программируя на С++ - это сделать сложнее, но если вы это сделаете, то вам оторвёт ногу целиком".
smile


Автор: Void 13.1.2006, 23:14
dronzo
Так и быть, спрячусь за Мастера smile Хотя смысл все-таки отличается.

Автор: DrLazy 14.1.2006, 01:21
dronzo
Вывод, не цельтесь себе в ногу, даже в шутку smile

Автор: Vendigo 17.1.2006, 18:42
Привет всем, это опять я. Изучение продвигается, сейчас я осваиваю классы. Предыдущий пример со структурой я переписал в виде класса:
Код

class Data_list
{
    char name[64];        // Имя
    int birthday;         // День рождения год.месяц.число
    char address[64];     // Адресс
    int telephone;        // Телефон
    char nik[32];         // Ник
    char sex;             // Пол m/w/n
    char company[32];     // Место работы
    char note[1024];      // Заметки
public:
    Data_list();                    // Конструктор

    void clear();                   // Очистка данных

    int name_put(char *str);        // Ввод данных
    int birthday_put(int a);
    int address_put(char *str);
    int telephone_put(int a);
    int nik_put(char *str);
    int sex_put(char s);
    int company_put(char *str);
    int note_put(char *str);

    char    *name_get();                         // Получение данных
    int     birthday_get();
    char    *address_get();
    int     telephone_get();
    char    *nik_get();
    char    sex_get();
    char    *company_get();
    char    *note_get();

};


Создал массив объектов:
Код

const int size_list = 100;
Data_list man[size_list];


Но опять таки все уперлось в получение строки из консоли. Void пишет, что можно использовать fgets() (вместо gets() которая не работает).

Нашел её прототип в справке:
char *fgets(char *s, int n, FILE *stream);
Объясните параметр FILE *stream, про потоки я еще ничего не знаю, так что... помогите.


Автор: Vendigo 17.1.2006, 19:21
Несколько соображений по поводу классов. Хочу узнать у вас правильно ли я их понимаю.

Объекты, которые определяются на основе классов, объединяют в себе данные и методы с помощью которых можно работать с этими данными.

Данные нужно описывать в закрытой части класса, чтобы ограничить их использование вне класса. Таким образом данные становятся недоступны из программы, невидимы. Что бы работать с данными нужно использовать методы - функции которые описаны в открытой части класса.

В этих функциях нужно проверять правильность ввода/вывода значений в/из закрытых данных, тем самым защищая их.

То есть в описанном мною классе Data_list в поле int birthday храниться дата рождения. А через функцию int birthday_put(int a) я получаю эту дату. И в ней я должен предусмотреть что бы вводимое значение являлось действительной датой.
Например функция будет возвращать 1 если пользователь ввел правильный формат и полю birthday присвоено значение. И 0, если формат не верен, и данные не записаны. А в программе я буду обрабатывать эти значения. Так?
Добавлено @ 19:24
Еще небольшой вопрос. Я работаю в Builder 6, и слева от текста кода, в проводнике, у меня отображается структура класса. Так вот когда я меняю объявление класса эта структура не меняется. Подскажете, как это лечится.

Автор: Romikgy 18.1.2006, 13:30
Вообщето
Цитата(Vendigo @ 17.1.2006, 17:42 Найти цитируемый пост)

char *fgets(char *s, int n, FILE *stream);

то для работы с файлами , имхо.

Автор: Vendigo 18.1.2006, 20:00
Млин, товарищи сертифицированные специалисты. Может разьясните как правильно получить строку из консоли?

А то чегой то у меня smile

Вот полный текст программы:
Код

#include<iostream>
#include<stdio.h>

using namespace std;
//---------------------------------------------------------------------------
class Data_list
{
    char name[64];         // Имя
    int birthday;              // День рождения год.месяц.число
    char address[64];     // Адресс
    int telephone;           // Телефон
    char nik[32];             // Ник
    char sex;                  // Пол m/w/n
    char company[32];   // Место работы
    char note[1024];      // Заметки
public:
    Data_list();                    // Конструктор

    void clear();                   // Очистка данных

    int name_put(char *str);        // Ввод данных
    int birthday_put(int a);
    int address_put(char *str);
    int telephone_put(int a);
    int nik_put(char *str);
    int sex_put(char s);
    int company_put(char *str);
    int note_put(char *str);

    char    *name_get();                         // Получение данных
    int     birthday_get();
    char    *address_get();
    int     telephone_get();
    char    *nik_get();
    char    sex_get();
    char    *company_get();
    char    *note_get();

};

Data_list::Data_list()
{
    name[0] = '\0';
    birthday = 0;
    address[0] = '\0';
    telephone = 0;
    nik[0] = '\0';
    sex = 'n';
    company[0] = '\0';
    note[0] = '\0';
};

void Data_list::clear()
{
    name[0] = '\0';
    birthday = 0;
    address[0] = '\0';
    telephone = 0;
    nik[0] = '\0';
    sex = 'n';
    company[0] = '\0';
    note[0] = '\0';
}

//-------- получение данных ------- Data_list--------------
int Data_list::name_put(char *str)
{
    for(int i=0; str[i]; i++)
        name[i] = str[i];
    return 1;
}

int Data_list::birthday_put(int a)
{
     birthday = a;
     return 1;
}

int Data_list::address_put(char *str)
{
    for(int i=0; str[i]; i++)
        address[i] = str[i];
    return 1;
}

int Data_list::telephone_put(int a)
{
    telephone = a;
    return 1;
}

int Data_list::nik_put(char *str)
{
    for(int i=0; str[i]; i++)
        nik[i] = str[i];
    return 1;
}

int Data_list::sex_put(char s)
{
    sex = s;
    return 1;
}

int Data_list::company_put(char *str)
{
    for(int i=0; str[i]; i++)
        company[i] = str[i];
    return 1;
}

int Data_list::note_put(char *str)
{
    for(int i=0; str[i]; i++)
        note[i] = str[i];
    return 1;
}

//-------- возвращение данных ---- Data_list --------------------
char *Data_list::name_get()    { return name; }
int Data_list::birthday_get()  { return birthday; }
char *Data_list::address_get() { return address; }
int Data_list::telephone_get() { return telephone; }
char *Data_list::nik_get()     { return nik; }
char Data_list::sex_get()      { return sex; }
char *Data_list::company_get() { return company; }
char *Data_list::note_get()    { return note; }
//---------------------------------------------------------------

const int size_list = 100;
Data_list man[size_list];

void output();
void input();
void clear();

int main()
{
    int a = 1;
    do
        {
        cout << "\n    MENU";       //Показываем меню
        cout << "\n 1 Output";
        cout << "\n 2 Input";
        cout << "\n 3 Poisk";
        cout << "\n 4 Clear";
        cout << "\n 0 Exit\n";
        cin >> a;

        switch(a)
            {
            case 1: output();
            break;
            case 2: input();
            break;
            case 3: cout << "\n Esche ne gotovo";
            break;
            case 4: clear();
            break;
            }

        } while (a);

    return 0;
}
//---------------------------------------------------------------------------

void output()
{
 for (int i=0; i < size_list; i++)   //Перебираем массив
    {
    if(*man[i].name_get())    //Если есть имя выводим данные
        {
        cout << "\nname: " << *man[i].name_get();
        cout << "\nbirthday(19791001): " << man[i].birthday_get();
        cout << "\naddress: " << *man[i].address_get();
        cout << "\ntelephone: " << man[i].telephone_get() << '\n';
        }
    }
}

void input()
{
    int  a = 1;
    char str[64];
    int  n;

    do
        {
        int i;
        for(i = 0; i < size_list; i++)
            if( *man[i].name_get() == '\0' ) break;  // Ищем пустую строку
            
        if(i == size_list)                          // Если цикл прошел весь
            {                                       // свободных строк нет
            cout << "no memory\n";
            return;
            }

        cout << "\ninput name: ";         //Вводим данные
        gets(str);
        man[i].name_put(str);

        cout << "\ninput addres: ";
        gets(str);
        man[i].address_put(str);

        cout << "\ninput birthday(19791001): ";
        cin >> n;
        man[i].birthday_put(n);

        cout << "\ninput telephone: ";
        cin >> n;
        man[i].telephone_put(n);

        cout << "\nREPET? (Yes-1/No-0)";   //Запрос повторного ввода
        cin >> a;
        } while(a);                        //Повтор ввода при необходимости
}

void clear()
{
    for(int i = 0; i < size_list; i++)
    man[i].clear();
    cout << "\nData clear";
}


Так тож не получается:
Код

        cout << "\ninput name: ";         //Вводим данные
        cin.getline(str, sizeof(str));
        man[i].name_put(str);

Автор: asdf 18.1.2006, 21:48
Код
#include<iostream>
#include<stdio.h>    
using namespace std;    
//---------------------------------------------------------------------------    
class Data_list    
{    
    char name[64];         // Имя    
    int birthday;              // День рождения год.месяц.число    
    char address[64];     // Адресс    
    int telephone;           // Телефон    
    char nik[32];             // Ник    
    char sex;                  // Пол m/w/n    
    char company[32];   // Место работы    
    char note[1024];      // Заметки    
public:    
    Data_list();                    // Конструктор    
    void clear();                   // Очистка данных    
    int name_put(char *str);        // Ввод данных    
    int birthday_put(int a);    
    int address_put(char *str);    
    int telephone_put(int a);    
    int nik_put(char *str);    
    int sex_put(char s);    
    int company_put(char *str);    
    int note_put(char *str);    
    char    *name_get();                         // Получение данных    
    int     birthday_get();    
    char    *address_get();    
    int     telephone_get();    
    char    *nik_get();    
    char    sex_get();    
    char    *company_get();    
    char    *note_get();    
};    
Data_list::Data_list()    
{    
    name[0] = '\0';    
    birthday = 0;    
    address[0] = '\0';    
    telephone = 0;    
    nik[0] = '\0';    
    sex = 'n';    
    company[0] = '\0';    
    note[0] = '\0';    
};    
void Data_list::clear()    
{    
    name[0] = '\0';    
    birthday = 0;    
    address[0] = '\0';    
    telephone = 0;    
    nik[0] = '\0';    
    sex = 'n';    
    company[0] = '\0';    
    note[0] = '\0';    
}    
//-------- получение данных ------- Data_list--------------    
int Data_list::name_put(char *str)    
{    
    for(int i=0; str[i]; i++)    
        name[i] = str[i];    
    return 1;    
}    
int Data_list::birthday_put(int a)    
{    
     birthday = a;    
     return 1;    
}    
int Data_list::address_put(char *str)    
{    
    for(int i=0; str[i]; i++)    
        address[i] = str[i];    
    return 1;    
}    
int Data_list::telephone_put(int a)    
{    
    telephone = a;    
    return 1;    
}    
int Data_list::nik_put(char *str)    
{    
    for(int i=0; str[i]; i++)    
        nik[i] = str[i];    
    return 1;    
}    
int Data_list::sex_put(char s)    
{    
    sex = s;    
    return 1;    
}    
int Data_list::company_put(char *str)    
{    
    for(int i=0; str[i]; i++)    
        company[i] = str[i];    
    return 1;    
}    
int Data_list::note_put(char *str)    
{    
    for(int i=0; str[i]; i++)    
        note[i] = str[i];    
    return 1;    
}    
//-------- возвращение данных ---- Data_list --------------------    
char *Data_list::name_get()    { return name; }    
int Data_list::birthday_get()  { return birthday; }    
char *Data_list::address_get() { return address; }    
int Data_list::telephone_get() { return telephone; }    
char *Data_list::nik_get()     { return nik; }    
char Data_list::sex_get()      { return sex; }    
char *Data_list::company_get() { return company; }    
char *Data_list::note_get()    { return note; }    
//---------------------------------------------------------------    
const int size_list = 100;    
Data_list man[size_list];    
void output();    
void input();    
void clear();    
int main()
{    
        int a = 1;
    do    
        {    
                cout << "\n    MENU";       //Показываем меню
        cout << "\n 1 Output";    
        cout << "\n 2 Input";    
        cout << "\n 3 Poisk";    
        cout << "\n 4 Clear";    
        cout << "\n 0 Exit\n";    
                cin >> a;
                switch(a)
            {    
            case 1: output();    
                        break;
            case 2: input();    
                        break;
                        case 3: cout << "\n Esche ne gotovo";
            break;    
            case 4: clear();    
                        break;
            }    
        } while (a);    
        return 0;
}
//---------------------------------------------------------------------------    
void output()    
{    
 for (int i=0; i < size_list; i++)   //Перебираем массив
        {
        if(*man[i].name_get())    //Если есть имя выводим данные
                {
                cout << "\nname: " << /***/man[i].name_get();
                cout << "\nbirthday(19791001): " << man[i].birthday_get();
                cout << "\naddress: " << /***/man[i].address_get();
                cout << "\ntelephone: " << man[i].telephone_get() << '\n';
        }    
    }    
}
void input()
{
        int  a = 1;
    char str[64];    
    int  n;    
    do    
        {    
                int i;
                for(i = 0; i < size_list; i++)
            if( *man[i].name_get() == '\0' ) break;  // Ищем пустую строку    
             
        if(i == size_list)                          // Если цикл прошел весь    
            {                                       // свободных строк нет    
            cout << "no memory\n";    
            return;    
            }    
                cout << "\ninput name: ";         //Вводим данные
                //gets(str);
                cin >> ws;
                cin.getline(str, sizeof str);
                man[i].name_put(str);
                cout << "\ninput addres: ";
                //gets(str);
                cin.getline(str, sizeof str);
                man[i].address_put(str);
                cout << "\ninput birthday(19791001): ";
                cin >> n;
                man[i].birthday_put(n);
        cout << "\ninput telephone: ";    
        cin >> n;    
                man[i].telephone_put(n);
                cout << "\nREPEAT? (Yes-1/No-0)";   //Запрос повторного ввода
                cin >> a;
                } while(a!=0);                        //Повтор ввода при необходимости
                //        char('0') == int(48)
}
void clear()    
{
    for(int i = 0; i < size_list; i++)    
        man[i].clear();
        cout << "\nData clear";
}

Автор: asdf 18.1.2006, 22:26
Цитата
Данные нужно описывать в закрытой части класса, чтобы ограничить их использование вне класса. Таким образом данные становятся недоступны из программы, невидимы. Что бы работать с данными нужно использовать методы - функции которые описаны в открытой части класса.

ещё ты можешь получать доступ к закрытым членам класса, указав функцию не являющуюся членом, как friend в его объявлении.
Код
  class A {
      friend A foo(A, A);
      //...
  };

Автор: Vendigo 19.1.2006, 00:32
Спасибо asdf, вроде работает. Сейчас уже поздно, завтра буду разбираться.
smile smile smile

Автор: Vendigo 20.1.2006, 20:15
1. Все, разобрался smile
Оказывается у меня и здесь еще была ошибка:
Код

 cout << "\nname: " << *man[i].name_get();

я получал первый символ а не указатель на него!

2. Подскажите пожалуйста функцию которая возвращает код символа. Перерыл все свои книги и весь форум не могу найти такой простой вещи.

Автор: Void 20.1.2006, 20:28
Цитата(Vendigo @ 20.1.2006, 22:15 Найти цитируемый пост)
2. Подскажите пожалуйста функцию которая возвращает код символа. Перерыл все свои книги и весь форум не могу найти такой простой вещи.

Ее нет smile Переменная типа char может служить и в качестве числового значения.

Автор: Mayk 20.1.2006, 20:50
Цитата(Vendigo @ 21.1.2006, 00:15 Найти цитируемый пост)

2. Подскажите пожалуйста функцию которая возвращает код символа. Перерыл все свои книги и весь форум не могу найти такой простой вещи.

Просто кастаните в int.
Код

int main(){
    char c; int i;
    cin >> c;
    i = c;
    cout << c << " has code " << i  //1 способ
             << "\nhas code " << (int) c << endl; //2 способ

}




Теперь потабаним.
Цитата(blackofe @ 14.1.2006, 02:22 Найти цитируемый пост)

и какой-нибудь strcat() тоже нельзя использовать. а указатели совершенно не
рекомендуется использовать - мало ли что с их помощью можно натворить! а уж new - просто под замок - потому что сплошь и рядом забывают вызывать ответный delete.
вывод: не программируйте, други мои. это опасно для жизни.

Почти согласен. Только не так категарично.
strcat действительно не следует использовать в общем случае. Точно так же как не стоит использовать strcpy и sprintf.
Вместо них лучше использовать strncat, strncpy, snprintf (пример из жизни - скаченная и собранная quake1 у меня вылетала, так как там в Sys_Printf использовали vsprintf на 1024 байтный буфер, а строка(которая содержала всякие характеристики видюхи, и вообще была юзеру(мне) не нужна) получалась более 1024 символов. Результат - Segmentation fault).
Про new - есть такие замечательные штуки как auto_ptr и shared_ptr, которые при определенным стечении обстоятельств позволят избежать утечек памяти и не вызывать delete.
Указатели порой действительно можно заменить ссылками, что а) предотвратит передачи NULL'а, и кроме того б) увеличит скорость разработки , так как вместо "if(a) a->b" можно будет писать "a.b" :-)
Вывод: используйте безопасные функции, и ваши волосы будут мягкими и пушистими.
Цитата(blackofe @ 14.1.2006, 02:22 Найти цитируемый пост)

логика таки в моих словах есть.

Соглсен smile

зы. Вот чем хорош стандарт - там ф-ции snprintf и sprintf описываются рядом. Во всяких книжках "с++ за обеденный перерыв" (во всяком случае в тех, что попадались мне) такого можно не дождаться. Кстати, в С99 ф-ция snprintf(7.19.6.5) описывается ДО sprintf(7.19.6.6) smile

Автор: Vendigo 20.1.2006, 21:25
Void
Mayk
Спасибо! Всего труднее найти то, что у тебя перед глазами smile

Можете еще объяснить про кодировки?
Я сделал так:
Код

int main()
{

    char c;
    int i;

    for(int j = 0; j < 256 ; j++)
    {
        c = j;
        cout << "int- " << j << " char- " << c << endl;
    };


    cin >> i;
    return 0;
}


И получил таблицу символов. Так эти символы отображаются в консоли. Что то мне подсказывает что в оконном приложении символы были бы другие (или расположенны по другому).

И еще такой вопрос:
Цитата(Vendigo @ 17.1.2006, 19:21 Найти цитируемый пост)

Я работаю в Builder 6, и слева от текста кода, в проводнике, у меня отображается структура класса. Так вот когда я меняю объявление класса эта структура не меняется. Подскажете, как это лечится.


Автор: blackofe 20.1.2006, 21:43
Цитата(Vendigo @ 20.1.2006, 21:25)
И получил таблицу символов. Так эти символы отображаются в консоли. Что то мне подсказывает что в  оконном приложении символы были бы другие (или расположенны по другому).

вполне возможно. хотя бы потому, что оконное приложение могло использовать windows-кодировку, а консольное - dos-кодировку. про кодировку тут говорили не раз. воспользуйся поиском. к примеру, можно поискать слово "locale".

Автор: Fin 20.1.2006, 21:44
Цитата

И получил таблицу символов. Так эти символы отображаются в консоли. Что то мне подсказывает что в оконном приложении символы были бы другие (или расположенны по другому).

Что то тебе подсказывает правильно. Досовская русская кодировка (CP-866) отличается от кодировки Винды (Windows-1251) в верхней части таблици. До символа с номером 127 все кодировки повторяются. Как выглядит кодировка можно посмотреть Character Map которая идет в комплекте постаки винды. Там нужно вызвать на показ любой шрифт соответствуюший кодировке винды. Я например смотрю или Arial или Courier New Cyr.

Автор: asdf 22.1.2006, 13:07
Цитата
Еще небольшой вопрос. Я работаю в Builder 6, и слева от текста кода, в проводнике, у меня отображается структура класса. Так вот когда я меняю объявление класса эта структура не меняется. Подскажете, как это лечится.

переоткрытием проекта.
если перед изменением объявления ты переходишь к нему 2х кликом в проводнике классов, структура должна правиться сходу ....

Автор: Vendigo 25.1.2006, 19:21
Ничего не понимаю smile

Я написал код который как я думаю выводит DOS кодировку символов. Но обратное преобразование не получается т.е. (int)c возвращает странный код.
Например если char c = 'б' то (int)c = -95 smile

Код

int main()    
{    
    char c;    
    int i;    
    for(int j = 0; j < 256 ; j++)    
    {    
        c = j;    
        cout << "int- " << j << " char- " << c << endl;    
    };    

    cin >> c;         // если здесь ввести русскую букву, то получаем странный результат
    cout << "char: " << c << "  int: " << (int)c << '\n'; 

    cin >> i;
    return 0;
}

Автор: Void 25.1.2006, 19:57
Объяви c, как unsigned char.

Автор: Vendigo 25.1.2006, 22:22
Все понял! Спасибо Void smile
Если у меня char то коды лежат в пределах от -128 до 127 !
Чтоб я делал без этого форума!

Автор: Vendigo 12.2.2006, 21:45
Всем доброго времени суток smile Я продолжаю изучение С++, и по мере продвижения по руководству Герберта Шилдта "С++ Базовый курс" у меня вновь возникли вопросы.

Главный вопрос, конечно же, остался: Смогу ли я когда-нибудь выучить этот С++? И если да, то сколько мне его еще штудировать?

Но появляются и более "низменные" вопросы. Так в главе "Перегрузка операторов" автор рассматривает создание своего класса строк:
Код

#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
//---------------------------------------------------------------------------
class str_type
{
    char string [255];
public:
    str_type(char *str = "") { strcpy(string, str); }  
    str_type operator+(str_type str);   
    str_type operator+(char *str);      
    str_type operator=(char *str);      
    str_type operator=(str_type str);   
    void show_str() { cout << string; }
};

// 
str_type str_type::operator+(str_type str)
{
    str_type temp;
    strcpy(temp.string, string);
    strcat(temp.string, str.string);
    return temp;
}

// 
str_type str_type::operator+(char *str)
{
    str_type temp;
    strcpy(temp.string, string);
    strcat(temp.string, str);
    return temp;
}

// Присваивание строки с завершающим нулем 
str_type str_type::operator=(char *str)
{
    str_type temp;

    strcpy(string, str);
    strcpy(temp.string, string);
    return temp;
}

// Перегрузка оператора присваивания
str_type str_type::operator=(str_type str)
{
    strcpy(string, str.string);
    return *this;
}


int main()
{
    str_type a(" Vsem "), b("privet"), c;

    c = a + b;
    c.show_str();

    c = c + " privet";
    c.show_str();

    c = " Ato srabotalo ";
    c.show_str();

    int w;
    cin >> w;
    return 0;
}


Вопрос такой: Зачем в этом классе перегрузка оператора присваивания?
Ведь класс не содержит в своих данных указателей. Операция присваивания, которая определена по умолчанию (побитовая копия) прекрасно работает. Зачем огород городить?

И второй вопрос: Присваивание строки с завершающим нулем.
Имхо так было бы проще:
Код

str_type str_type::operator=(char *str)
{
    strcpy(string, str);
    return *this;
}

Автор: Mayk 14.2.2006, 08:55
Цитата(Vendigo @ 13.2.2006, 01:45 Найти цитируемый пост)
Зачем в этом классе перегрузка оператора присваивания?
Ведь класс не содержит в своих данных указателей. Операция присваивания, которая определена по умолчанию (побитовая копия) прекрасно работает. Зачем огород городить?

Наверное, чтобы не копировать три сотни символов, если можно меньше скопировать.

А вообще strcpy надо заменить на strncpy(); А то на длинных строках будет ой.
В operator'ах и конструкторе char* заменить на const char*, и возвращать в operator='ах не str_type, а str_type&.


Автор: Vendigo 14.2.2006, 21:19
Цитата(Mayk @ 14.2.2006, 08:55 Найти цитируемый пост)
В operator'ах и конструкторе char* заменить на const char*

Насколько я понимаю, const char* в параметрах служит для того, чтобы функция не могла изменить переданный ей аргумент.

А это что значит? "возвращать в operator='ах не str_type, а str_type&."
( Я знаю, только, что &a значит "Получить адрес переменной а" )

Автор: Lotrex 15.2.2006, 09:08
Это значит, что фактически (на уровне команд) будет возвращатся не значение, а указатель. На уровне С++ будет отличие - такой указатель назыв. ссылкой, но разыменовывать его не надо - он как бы уже разыменован, и с ним надо обращатся как с переменной, содержащей некоторое значение, а не адрес. Отсюда существенное отличие записей
Код

str_type operator= (str_type &a)

и
Код

str_type &operator= (str_type &a)


отличия будут в выражениях типа следующего:
Код

str_type a, b, c;

c = "string";
a = b = c;

В первом случае значение возвращаемого пр-ра будет копироватся дважды - один раз внутри оператора b = c (при вызове оператора return str; где str имеет тип str_type) произойдет копирование в стек, потом - передача адреса содержимого стека в качестве входного параметра в операторе a = b.

Во втором случае в стек сначала будет копироватся значение не содержимого str, а ее адреса, и если str будет автоматической (стековой) переменной, то во втором операторе (a = b) произойдет ошибка.

Автор: Vendigo 2.3.2006, 20:54
Добрый вечер всем кто в сети smile
Упражнялся я со своим Builderom и в результате неких экспериментов накопил к вам ряд вопросов.

Допустим мне нужно чтоб функция возвращала двумерный массив. Например такой
Код

int dim[25][25];


Целиком массив из функции вернуть нельзя, так же как нельзя в нее массив передать. Для этого используется указатель на первый элемент массива так?

Но как оказалось недостаточно объявить ф-ию:
Код

int *massiv()


и в ней написать
Код

return dim; 

компилятор ругается
"E2034 Cannot convert 'int ( *)[25]' to 'int *'" – не знаю, что это значит. Хоть учебник и утверждает, что "использование имени массива без индекса генерирует указатель на первый элемент"

Я поступил таким образом:
Код

int *p;
p = &dim[0][0];
return p;


И только было возрадовался своей хитрости, сумевшей обмануть компилятор, как обнаружил, что программа все равно не работает!!!

Меня ждало жестокое разочарование! Массив созданный внутри функции, суть локальные переменные, и указатель на его начало, никоим образом мне помочь не может. Как только функция завершается память тотчас освобождается. В итоге я остался там же где и начал. Неужели нет способа возвратить из функции массив?

Весь код:
Код

int *massiv()
{
    //randomize();
    int s = 0;
    int dim[r][r];
    int *p;
    


    for(int i = 0; i < r; i++)
        for(int j = 0; j < r; j++)
            {
            dim[i][j] = random(101);
            s = s + dim[i][j];
            }
        cout << "S: " << s << "\n";
    p = &dim[0][0];
    return p;
}

Автор: sergejzr 2.3.2006, 20:55
Модератор: Название темы должно отражать ее суть!
Модератор: Пожалуйста, один топик - один вопрос.

Автор: Vendigo 2.3.2006, 20:57
И другой вопрос, уже не такой философско-риторический, допустим, я хочу передать двумерный массив в функцию.
Код

int dim[25][25]

И использую указатель int *d в ее параметре.

Как мне обращаться к элементам этого массива?
d[i][j] – не работает (в принципе понятно почему)
писать что то вроде этого:
d[i*r+j] , где r – длинна строки в массиве?

Автор: MAKCim 2.3.2006, 22:06
Цитата

d[i*r+j] , где r – длинна строки в массиве?

может d[i*(r-1)+j], в C/C++ обычно первый индекс 0
Добавлено @ 22:07
Цитата

Меня ждало жестокое разочарование! Массив созданный внутри функции, суть локальные переменные, и указатель на его начало, никоим образом мне помочь не может. Как только функция завершается память тотчас освобождается. В итоге я остался там же где и начал. Неужели нет способа возвратить из функции массив?

либо память динамически выделять, либо пользоваться std::vector, можешь написать свой класс, ...

Автор: Vendigo 2.3.2006, 22:49
Цитата(MAKCim @ 2.3.2006, 22:06 Найти цитируемый пост)
либо память динамически выделять, либо пользоваться std::vector, можешь написать свой класс, ...

Точно!
Можно же так
Код

int * p = new int [25][25];


vector я еще не разбирал, а свой класс писать для такой простой вещи...

Автор: Void 2.3.2006, 23:36
Цитата(Vendigo @ 3.3.2006, 00:49 Найти цитируемый пост)
int * p = new int [25][25];

Ты компилировать это пробовал?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)