Lance Mason Robinson wrote:

> I'm having problems using gettext() and puttext().  I'm trying to use 
> them

> to save the screen and restore the screen.  Sometimes when I'm running


> the program, it locks up after I call gettext() and sometimes after I
> call puttext().  I was thinking maybe the function is getting confused 
> by
> other included files.  Here's how I am using it in my program..

> void * screen;
> //save screen
> gettext(1,1,80,25,screen);
> //here I am changing the screen, for example in one instance if they 
> press
> //F1 it shows a help screen with all the commands available.
> //then after they exit the help screen...
> //restore screen
> puttext(1,1,80,25,screen);

> If I remove all the gettext()'s and puttext()'s from my program then 
> it
> works great.  Any ideas how to fix it?  Or alternative methods to save
> & restore the screen state?

> Lance

Lance,

Your problem is easy to fix. YOU have to allocate the memory you pass 
to gettext. It will use it to store the display info. (The lockups
are due to a memory violation.) The memory space needed for the array
can be calculated the following way:

   bytes = number_of_rows * number_of_columns * 2

   where number_of_rows    = bottom - top + 1
   and   number_of_collums = right - left + 1

In your example the following lines would do it:

   #include <conio.h>
   
   // allocate 80*25*2 = 4000 bytes
   void screen[4000];
   // save screen
   gettext(1,1,80,25,screen);
   // your stuff
   // ...
   //
   // restore screen
   puttext(1,1,80,25,screen);

'언어 > C' 카테고리의 다른 글

[Linked List] 연결리스트를 활용한 도서관리prog  (0) 2017.02.08
[CubeBite] File_Create_Write 함수  (0) 2017.02.08
[Tip] File I/O Error 다루는 법  (0) 2016.11.05
구조체의 크기와 pragma pack  (0) 2016.10.28
비트필드 구조체  (0) 2016.10.27
Posted by 知彼知己百戰不殆
,

이중 연결 리스트를 활용한 도서관리 프로그램. 

제작 환경: MacBookPro Letina 2014 OS X

BookManagement_Prog-master.zip


[git hub 주소]

https://github.com/njinx0612/BookManagement_Prog.git


git@github.com:njinx0612/BookManagement_Prog.git

'언어 > C' 카테고리의 다른 글

Conio.h의 gettext 사용 시 문제점  (0) 2017.08.14
[CubeBite] File_Create_Write 함수  (0) 2017.02.08
[Tip] File I/O Error 다루는 법  (0) 2016.11.05
구조체의 크기와 pragma pack  (0) 2016.10.28
비트필드 구조체  (0) 2016.10.27
Posted by 知彼知己百戰不殆
,

저수준 파일 입력 함수

인자 설명

location_filename: 파일위치+파일이름

write_data: 파일에 쓸 데이터

size: 파일 사이즈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
 
int file_create_write(char* location_filename, char* write_data, int size)
{
    int file_descriptor;
    char add_write[1024]={0};
    int ret;
    int iCnt;
    printf("\n");
    printf("[D] loca: %s\n", location_filename);
    printf("[D] data: %s\n", write_data);
    printf("[D] File Open start...\n");
 
#if 0
    /* replace a data to file  */
    if( (file_descriptor = open(location_filename,O_CREAT|O_TRUNC|O_WRONLY,0644)) > 0 )
    {
        write(file_descriptor, write_data, size);
        close(file_descriptor);
        printf("[D] File close\n");
    }
    else
    {
        printf("File Open Error...\n");
        return -1;
    }
#endif
 
    /* attach a data to file  */
    if( (file_descriptor = open(location_filename,O_CREAT|O_WRONLY|O_APPEND,0644)) > 0 )
    {
        printf("Open file_descriptor=%d\n",file_descriptor);
        if( write(file_descriptor, write_data, size== -1 )
        {
            printf("File write Error...\n");
            return -3;
        }
    
#if 0
        printf("[ADD] Input data to file (nothing: Press Enter...) : ");
        fgets(add_write, sizeof(add_write), stdin);
        //scanf("%s",add_write);
        
        for(iCnt=0; iCnt<strlen(add_write); iCnt++)
        {
            printf("[D] add_write[%d]=%c[0x%02x]\n",iCnt,add_write[iCnt],add_write[iCnt]);
        }
        
        if*(add_write) == '\n' )
        {
            break;
        }
        
        else
        {
            write(file_descriptor, add_write, sizeof(add_write)-1);
            for(iCnt=0; iCnt<sizeof(add_write); iCnt++)
            {
                add_write[iCnt]=0;
                printf(".");
            }
            
        }
#endif
 
    
        close(file_descriptor);
        printf("[D] File close\n");
    }
    
    else
    {
        printf("File Open Error...\n");
        return -2;
    }
 
    return 0;
}
 
int main(int argc, char* argv[])
{
    int ret,iCnt = 0;
    char file_location_name [1024= {0};
    char file_write [1024= {0};
 
    if( argc <= 1 || argc > 2 )
    {
        printf("Argument Error...\n");
        printf("Using manual: ./(execution_file_name) (file_location)\n");
        return -1;
    }
 
    while(1)
    {
        iCnt = 0;
        printf("\n Input data to file : ");
        fgets(file_write, sizeof(file_write), stdin);
        //for(iCnt=0; iCnt<strlen(file_write); iCnt++)
 
        while*(file_write+iCnt) != '\n' )
        {
            printf("[D] file_write[%d]=%c[0x%02x]\n",iCnt,file_write[iCnt],file_write[iCnt]);
            iCnt++;
        }
 
        if( file_write[0== '\n' )
        {
            break;
        }
 
        /* file_write end is '\n' */
        ret = file_create_write( argv[1], file_write, strlen(file_write) );
        
        
        for(iCnt=0; iCnt<strlen(file_write); iCnt++)
        {
            file_write[iCnt]=0;
        }
    }
 
    /* remove '\n' */
    //ret = file_create_write( file_location_name, file_write, strlen(file_write)-1); 
    printf("[D] File open return=%d\n", ret);
 
    return 0;
    
}



Posted by 知彼知己百戰不殆
,

1. 헤더 파일을 추가한다

#include <errno.h>

2. printf로 error의 원인을 메세지로 띄운다.

printf("Error: %s\n", strerror(errno));


혹은

perror("File Open Error");

이렇게 코딩을 해 놓으면 나중에 에러가 발생했을 때, File Open Error: (파일오픈에러의 이유)가 나타난다.

'언어 > C' 카테고리의 다른 글

[Linked List] 연결리스트를 활용한 도서관리prog  (0) 2017.02.08
[CubeBite] File_Create_Write 함수  (0) 2017.02.08
구조체의 크기와 pragma pack  (0) 2016.10.28
비트필드 구조체  (0) 2016.10.27
volatile 형한정어  (0) 2016.10.19
Posted by 知彼知己百戰不殆
,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
 
typedef struct 
{
        char a;
        char c;
        short d;
        char e;
        int b;
 
} Test_Struct;
 
int main()
{
        Test_Struct str_t;
        printf("\n[STRUCT]\n");
        printf("size=%d\n\n",sizeof(str_t));
}


char(1바이트) 2개 = 2바이트
short(2바이트) 1개 = 2바이트
char(1바이트) 1개 = 1바이트
int (4바이트) 1개 = 4바이트
= 총 9바이트

그런데 12바이트가 나왔다!


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
 
typedef struct 
{
        char a;
        char b;
        char c;
        char d;
        int e;
 
} Test_Struct;
 
int main()
{
        Test_Struct str_t;
        printf("\n[STRUCT]\n");
        printf("size=%d\n\n",sizeof(str_t));
}


char(1바이트) 4개 = 4바이트

int(4바이트) 1개 = 4바이트

= 총 8바이트

구조체 사이즈도 8바이트가 나왔다!


위의 코드와 아래 코드의 사이즈에서 왜 차이가 나는 것일까?

이유는 패딩비트가 추가되었기 때문이다. 몇몇 컴파일러는 구조체의 필드를 메모리에 위치시킬 때 중간에 빈 공간없이 이어서 할당하는 경우도 있지만, 대부분의 컴파일러는 성능향상을 위해 CPU가 접근하기 쉬운 위치에 필드를 배치한다. 그러다보니 중간에 빈 공간이 들어가게 되는데 이것을 패딩비트라고 부른다.

32bit CPU는 메모리에서 값을 읽어올 때 한 번에 32bit씩(4Byte)를 읽어온다. 그런데 레지스터가 읽는 블록의 경계에 걸쳐 멤버 변수가 생긴다면 메모리를 읽을 때 두 개의 블록을 읽는 문제가 발생한다.

예를 들면, 구조체 안에서 char a, int b 이런 식으로 4Byte 단위로 생성을 안 했을 때 문제가 발생한다. 만약 구조체 멤버 b변수에 접근하려고 하면 어떻게 될까? 

구조체의 시작 주소에서 32bit를 읽어와도 멤버 b의 비트에 모두 접근 할 수 없다. 그래서 두 번 메모리를 읽어서 첫 번째 읽은 값에서 뒤의 24bit(char 8bit를 뺀 부분)와 두 번째 읽은 값에서 앞의 8bit를 합쳐서 멤버 b의 값을 구할 수 있다. 하지만!!!!! 한 번에 할 수 있는 일을 두 번에 걸쳐서 하는 것이기 때문에 성능저하가 발생한다.

그래서 대부분의 컴파일러는 CPU가 접근하기 쉬운 메모리 위치에 필드를 배치시켜서 패딩비트가 자동으로 들어가게 된다.

즉, char a, int b라고 선언한 부분에서는 멤버 변수 a와 b사이에는 3byte의 패딩 비트가 들어간 것이다. 이렇게 하면 메모리를 3바이트나 낭비하게 되지만 각 멤버에 접근할 때 한 번씩만 메모리를 읽으면 되기 때문에 성능저하가 발생하지 않는다.


하지만! #pragma pack(1) 이란 전처리어를 사용하면, 구조체 사이즈가 달라진다!

size=12는 pragma pack을 사용하기 전의 구조체 사이즈이고, size=9는 pragma pack을 사용했을 때의 구조체 사이즈이다.

char(1Byte) + short(2Byte) + short(2Byte) + int(4Byte) = 9Byte

하지만 pragma pack을 사용하기 전에는 char + short + padding bit = 4Byte,

short + padding bit = 4Byte,

int = 4Byte.... 그래서 12바이트가 나온 것이다.

'언어 > C' 카테고리의 다른 글

[CubeBite] File_Create_Write 함수  (0) 2017.02.08
[Tip] File I/O Error 다루는 법  (0) 2016.11.05
비트필드 구조체  (0) 2016.10.27
volatile 형한정어  (0) 2016.10.19
scanf와 fgets 함수를 같이 사용하면서 나타나는 문제점  (0) 2016.10.19
Posted by 知彼知己百戰不殆
,

비트필드 구조체

언어/C 2016. 10. 27. 17:37

요즘은 안 쓰인다고 하지만 예전에 메모리가 귀하던 시절에는 메모리를 조금이라도 아끼기 위해서 사용되었다고 한다.

1
2
3
4
5
6
7
8
9
typedef struct
{
    char a:1;
    char b:1;
    char c:1;
    char d:1;
 
} _t_TestBit;
 


이렇게 비트필드 구조체를 작성하고 sizeof로 크기를 찍어보면 1바이트가 나온다.

1
2
3
4
5
6
7
8
9
typedef struct
{
    char a:2;
    char b:2;
    char c:2;
    char d:3;
 
} _t_TestBit;
 


이렇게 비트필드 구조체를 작성하고 sizeof로 크기를 찍어보면 2바이트가 나온다. (2,2,2,2)로 작성하면 1바이트가 나온다.


char를 사용하면 최소 1바이트 부터 값이 찍히지만 int를 사용하면 4바이트부터 값이 찍힌다.

비트필드를 사용할 때는 변수명을 안 적을 수도 있는데 만약 char :0; 이라고 적으면 현재 워드(char, int)의 미사용 비트를 모두 버린다. 혹은 char :1;이런 식으로 변수명을 안 적어도 비트를 버리는 역할만 한다.

Posted by 知彼知己百戰不殆
,

volatile 형한정어

언어/C 2016. 10. 19. 10:36

변수와 관련된 모든 연산에 대해 컴파일러가 '최적화' 규칙을 적용하지 않는다. <-> const와는 반대의 역할


CPU는 빠른 연산을 위해 캐시 메모리를 사용하는데, volatile로 선언된 변수는 캐시로 처리되지 못한다. 효율은 떨어질 수 있으나 주기억장치에 정보가 읽고 쓰이는 행위는 보장 받을 수 있다. 

Posted by 知彼知己百戰不殆
,

scanf와 fgets 함수를 같이 사용하면서 나타나는 문제점


fgets 함수를 먼저 쓰든 scanf를 먼저 쓰든 두 함수가 연속적으로 온다면 둘중에 한 개의 함수만 실행되고 나머지 함수는 무시된다. fgets 함수나 scanf함수는 입력 버퍼에 Enter키가 입력될 때까지 입력을 받고, 출력은 \n(개행문자) 전까지의 데이터를 출력해준다. 따라서 입력 버퍼에는 아직 \n(개행문자)가 남아있으므로 두 번째 함수가 실행될 때는 자동으로 개행문자 데이터가 남아있으므로 함수가 입력이 끝난 줄 알고 종료한다.

따라서 이런 현상을 방지하려면!!!!!!!


윈도우: fflush(stdin)

리눅스, UNIX: fpurge(stdin)

을 사용해서 입력 버퍼에 있는 내용을 비워내야 한다. 그리고 fflush 함수는 입력 버퍼를 비우는 함수가 아니라 출력 버퍼를 비우는 함수이다. 하지만 MS 윈도우가 C 표준을 지키지 않은 덕분에 이렇게 사용도 가능하다.


호환성을 생각하는 코드를 작성해야 한다면, scanf("%d %*c", ~~~)로 작성을 해야 한다.

%*c는 문자 하나를 입력 버퍼에서 읽어온 후 그냥 버린다는 의미이다.

Posted by 知彼知己百戰不殆
,
1
2
3
4
5
6
7
8
#include <stdio.h>
 
int main(void)
{
    char string[]="hello world";
 
    char* ptr="hello";
}


string 배열에 들어간 hello world는 프로그램이 실행되면서 스택 메모리에 저장된 hello world이다. 따라서 값의 수정이 가능하다.


하지만 포인터 ptr에 들어간 hello는 코드 영역(상수 영역=읽기 전용)에 hello가 저장돼 있고, 그것을 가리키는 주소값을 저장해논 변수라서 읽기만 가능하다. 즉, 값의 수정이 불가능하다.

'언어 > C' 카테고리의 다른 글

volatile 형한정어  (0) 2016.10.19
scanf와 fgets 함수를 같이 사용하면서 나타나는 문제점  (0) 2016.10.19
getc() 함수를 사용했을 때의 오류  (0) 2016.09.28
함수 포인터 컴파일 오류  (0) 2016.09.26
전처리문  (0) 2016.05.02
Posted by 知彼知己百戰不殆
,

getc() 함수를 사용했을 때의 오류


In file included from test_variable.c:1:0:

test_variable.c: In function ‘main’:

test_variable.c:13:11: error: too few arguments to function ‘_IO_getc’

   tempBuf=getc();

In file included from /usr/include/stdio.h:74:0,

                 from test_variable.c:1:

/usr/include/libio.h:434:12: note: declared here

 extern int _IO_getc (_IO_FILE *__fp);


코드:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>


int main(void)

{

        int buffer_cnt;

        char rx_buffer[255]={0};

        char tempBuf;


        while(1)

        {

                tempBuf=getc();

                printf("tempBuf=%d\n",tempBuf);

                rx_buffer[buffer_cnt++]=tempBuf;

                printf("tempBuf=%d\n",tempBuf);

        }

}


getc()함수에서 괄호 안에 어디서 입력을 받을 건지를 정해주어야 한다. 입력 받을 곳을 정해주지 않아서 발생하는 오류

get(0) => stdin에서 입력을 받겠다고 적어주면 오류가 사라진다.

Posted by 知彼知己百戰不殆
,