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


Автор: tenebris 10.9.2008, 09:30
Привет!!! Значит дело такое. Есть большая структура порядка 20 записей.
Все записи разного размера, т.е. надо считывать из файла определенное количество байт. Может здесь ошибка, но я использую тип char. Нужно считать в структуру файл. И вот здесь получается вот что. Допустим у меня есть последняя запись. Я её вывожу -всё нормально. Но как только я вывожу на экран предпоследнюю запись, он кроме неё выводит и последнюю, т.к. не видит конца строки. Что тогда говорить о первой - выводится вся структура. Как с этой проблемой справиться. Помню в паскале было всё легко. А здесь этот символ конца строки мешает. Может другой тип использовать. Дописывать символ конца строки очень напряжно если структура вырастит до 40 записей. Просьба пример привести на с, а не на с++. Спасибо.

Автор: andrew_121 10.9.2008, 09:33
tenebris, Это все классно! smile  Но не понятно smile 
Код выкладывай.

Автор: Mayk 10.9.2008, 09:41
ничего не понял, если честно, начиная отсюда.
Цитата(tenebris @  10.9.2008,  13:30 Найти цитируемый пост)
Есть большая структура порядка 20 записей.

В структуре не бывает записей. Никогда не было, никогда не будет. Нет такого понятия в си отродясь
Цитата(tenebris @  10.9.2008,  13:30 Найти цитируемый пост)
. Может здесь ошибка, но я использую тип char.

очевидно что в char можно считать ровно один байт.

Добавлено через 20 секунд
Цитата(andrew_121 @  10.9.2008,  13:33 Найти цитируемый пост)
Код выкладывай. 

+1

Автор: tenebris 10.9.2008, 10:00
Ну поле, поле. Запись это в паскале. Никак не могу перейти от него к си.

Добавлено через 5 минут и 32 секунды
Вот

Код

struct header
{
 char stack[4];
 char pc[4];
 char inter[9];
 char flag[2];
.
..
....
};

Вот, при выводу на экран h.flag - всё норма, показывается 2 байта в хексе. А вот когда я прошу вывести на экран h.inter ,мне показывается не только 9 байт но и ещё +2 байта след. пункта и т.д. А мне нужно точно, не вылезая на след. запись. Но здесь всё дело в конце строки. Но поля разного размра. Там инфа об образе. Как с этим бороться. Какой тип использовать?

Автор: xvr 10.9.2008, 10:16
Цитата(tenebris @ 10.9.2008,  10:00)
Ну поле, поле. Запись это в паскале. Никак не могу перейти от него к си.

Добавлено @ 10:05
Вот

Код

struct header
{
 char stack[4];
 char pc[4];
 char inter[9];
 char flag[2];
.
..
....
};

Вот, при выводу на экран h.flag - всё норма, показывается 2 байта в хексе. А вот когда я прошу вывести на экран h.inter ,мне показывается не только 9 байт но и ещё +2 байта след. пункта и т.д. А мне нужно точно, не вылезая на след. запись. Но здесь всё дело в конце строки. Но поля разного размра. Там инфа об образе. Как с этим бороться. Какой тип использовать?

В C строки (а у тебя все поля твоей структуры именно они и есть) завершаются нулем. Так что в inter например влезет только 8 символов (и 9й ноль). Если у тебя там будет 9 символов (или не будет нуля в конце) то любая функция C, работающая со строками, будет перебирать память за границами твоего inter, пока не найдет 0

Автор: andrew_121 10.9.2008, 10:50
Цитата(tenebris @  10.9.2008,  10:00 Найти цитируемый пост)
показывается не только 9 байт но и ещё +2 байта след. пункта и т.д.

Про выравнивание не забудь!

tenebris, Выложи еще код заполнения структуры + чтение из файла + запись в файл.

Автор: mes 10.9.2008, 13:39
Цитата(tenebris @  10.9.2008,  10:00 Найти цитируемый пост)
Ну поле, поле. Запись это в паскале. Никак не могу перейти от него к си.

в паскале запись это Record, a переменные класса также называются полями.

Автор: mrbrooks 10.9.2008, 13:48
Цитата(mes @  10.9.2008,  13:39 Найти цитируемый пост)
переменные класса также называются полями.

как они только не называются  smile 

Автор: tenebris 10.9.2008, 15:03
Блин что никто не поможет чтоль. Ща выложу код и ещё раз подробно расскажу

Автор: Lazin 10.9.2008, 15:08
 smile 
впервые встречаю настолько понятное описание проблемы smile 

Автор: tenebris 10.9.2008, 15:38
 smile 

Есть бинарный файл, к примеру avi.  У меня есть структура зоголовка файла. В свою структуры я пытаюсь прочесть этот заголовок.  В этом заголовке нету никаких концов строк- спец. символов. Потому что там указателе к примеру  данные о выделении памяти. Короче это всё условность. Делаю это так
Приведу два поля структура для простоты и наглядности.

Код

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

struct header
{
 unsigned char stack[4];
 unsigned char pc[5];
};

int main()
{
 header h;
 clrscr();
 FILE *avi;
 avi = fopen("c:\\1.avi","r");
 fseek(avi,0,SEEK_SET);
 fread(&h,1,sizeof(h),avi);
 return 1;
}

Вот.
При выводе последнего поля pc - он выводиться нормально.  Но когда я вывожу  stack, выводиться оно само плюс поле pc, т.к. нету конца строки. Как это побороть?

Автор: Fazil6 10.9.2008, 15:56
tenebris,  ну ты оригинал.... А что у нас с выравниванием при таком способе считывания? Ну вообще для вывода каждого поля в твоем случае нужно писать отдельную функцию, которая знает длину этого поля и выводит только его. А вообще лучше завести отдельную структуру с константами длин полей и считывать каждое поле по отдельности в цикле лепя каждому '\0' в конец.

Автор: tenebris 10.9.2008, 16:07
Цитата

 А что у нас с выравниванием при таком способе считывания


Не знаю про что ты.
Блин, ну а как пишут все проги для проигрывания файлов к примеру. Они же заголовок рассматривают. Это важная вешь, как они эту проблему решают. 
Длину каждого поля я знаю. Это определенные смещения, и каждое поле имеет свою длину 
т. е. константу. Нельзя там как-нить через указатели это реализовать.

Автор: Fazil6 10.9.2008, 16:12
Цитата(tenebris @  10.9.2008,  16:07 Найти цитируемый пост)
Не знаю про что ты.

в зависимости от длин полей и настроек компилятора между полями могут быть "дырки", а ты пишешь, так будто они всегда одно за другим идут
Цитата(tenebris @  10.9.2008,  16:07 Найти цитируемый пост)
Длину каждого поля я знаю. Это определенные смещения, и каждое поле имеет свою длину 

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

Автор: tenebris 10.9.2008, 16:48
Цитата

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


А что я разве этим не пользуюсь, когда в структуре обявляю переменную в 6 байт к примеру.

2) Второй вопрос появился. Допустим у меня в типе char записано значение 0XFFFF. Как мне его привести к типу int или другому целочисленному чтобы там тоже было ffff, но интерпретировался не как символ, а как число т.е. в десятичной системе 65535. Т.е. чтоб эти числа вывелись на экран

Добавлено через 9 минут и 27 секунд
2)

Код

 char slovo[2]={'a','c'};
 unsigned int i =(char)slovo;
 cout << i;

Почему при изменении букв, значение переменой i не меняется хотя оно формируется из внутреннего кода букв? 

Автор: korian 10.9.2008, 17:10
Цитата(tenebris @  10.9.2008,  14:38 Найти цитируемый пост)
При выводе последнего поля pc - он выводиться нормально

это случайность.

Цитата(tenebris @  10.9.2008,  14:38 Найти цитируемый пост)
Но когда я вывожу  stack, выводиться оно само плюс поле pc, т.к. нету конца строки. Как это побороть?

можно, например, преобразовать массив чаров в C-строку:
const int bufSize = 100;
char buff[bufSize];
strncpy(buff, h.stack, sizeof(h.stack));
buff[sizeof(h.stack)] = 0;
cout<<buff;
или вывести массив чаров в цикле посимвольно.

Цитата(Fazil6 @  10.9.2008,  15:12 Найти цитируемый пост)
в зависимости от длин полей и настроек компилятора между полями могут быть "дырки", а ты пишешь, так будто они всегда одно за другим идут

насколько я знаю, "дырки" могут быть только в конце структуры. т.е. между полями дырок быть не может.

Цитата(tenebris @  10.9.2008,  15:48 Найти цитируемый пост)
Почему при изменении букв, значение переменой i не меняется хотя оно формируется из внутреннего кода букв?

что-то дальше уже отвечать не хочется  smile 
Код

char slovo[2]={'a','c'};
unsigned int i = slovo[0];
cout << i;
i = slovo[1];
cout << i;

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

Автор: tenebris 10.9.2008, 17:32
Короче пришел я в тупик.
Никто не покажет функцию перевода  числа из строки  в число типа целого?

Добавлено @ 17:34
Цитата

имхо тут надо разбираться с основными понятиями языка... а в частности что такое массив, си-строка и чем отличается массив чаров от си-строки
.
ДАйти линки плиз.

Добавлено через 5 минут и 21 секунду
Цитата

и чем отличается массив чаров от си-строки.

Чем? smile  smile 

Автор: xvr 10.9.2008, 21:16
Цитата(tenebris @ 10.9.2008,  16:48)
2) Второй вопрос появился. Допустим у меня в типе char записано значение 0XFFFF. 

Тип char занимает 1 байт, и лежать в нем 0xFFFF не может - просто не уместится
Цитата

Как мне его привести к типу int или другому целочисленному чтобы там тоже было ffff, но интерпретировался не как символ, а как число т.е. в десятичной системе 65535. Т.е. чтоб эти числа вывелись на экран
Нифига не понял  smile Тебе нужно поле из 2х char'ов преобразовать в int?
Код

char s[2]={1,2};

short i=*(short*)s;
 
Цитата


Добавлено @ 16:58
2)

Код

 char slovo[2]={'a','c'};
 unsigned int i =(char)slovo;
 cout << i;

Почему при изменении букв, значение переменой i не меняется хотя оно формируется из внутреннего кода букв?
Оно формируется из адреса массива slovo, а не из его содержимого, поэтому и не меняется


Автор: Mayk 11.9.2008, 05:45
Цитата(korian @  10.9.2008,  21:10 Найти цитируемый пост)
насколько я знаю, "дырки" могут быть только в конце структуры. т.е. между полями дырок быть не может.

неа. выравнивание полей не отменяли.
Код

#include <stdio.h>
#include <math.h>

struct A{
    char c;
    int a;
    char b;
};
struct B{
    char c;
    char b;
    int a;
};
int main()
{
    printf("%d %d\n",sizeof(A), sizeof(B));
}

Цитата

12 8


Автор: korian 11.9.2008, 10:45
Цитата(Mayk @  11.9.2008,  04:45 Найти цитируемый пост)
неа. выравнивание полей не отменяли.

даже так  smile 
понял, спасибо

Автор: inside_pointer 12.9.2008, 01:02
Цитата(tenebris)

Короче пришел я в тупик.
Никто не покажет функцию перевода  числа из строки  в число типа целого?


Код

#include <stdio.h>
 
main()
{
    
    char line[100];
    
    sprintf(line, "%g", 2.3e-8);
    
    printf("%s\n", line);
    
    return 0;
}


здесь вещественное число 0,000000023 записывается в строку line

противоположная функция sscanf

Код

#include <stdio.h>
 
main()
{
    char line[100] = "120000";
    int num;
    
    sscanf(line, "%d", &num);
    
    printf("%d\n", num);
    
    return 0;
}


обрати внимание на & возле num, это очень важно

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