c언어하면 포인터라는 개념이 매우 중요하게 다뤄지며 이 포인터를 잘 다뤄야 c언어를 제대로 이해하고 사용할 수 있다고 합니다.

오늘은 포인터에 대해 살펴보려합니다.

<목차>

  1. 포인터란?
  2. 포인터는 언제 주로 사용되는가?
  3. 활용은 어떻게 될까?
  4. c언어에서 주의해야할 포인터 개념(   ex) 문자열 => char형 포인터로 구현이 가능하다.   )
  5. 실습 예제를 통해 구체적으로 알아보자 (다음의 블로그에 올릴 예정입니다.)

 

 

1. 포인터란?

변수 이다!! 기본데이터타입을 앞의 블로그에서 다루었는데 기본 데이터 타입중 int는 정수형 데이터 타입을 저장

이를 포인터에도 적용을 해보면 변수 주소정보(데이터)를 저장한다고 볼 수 있습니다.

int *pi;포인터 변수 선언을 하며 pi = &i; (i는 100으로 정의되어있다고 가정을 합니다.)로 정의를 할 수 있습니다.

**위에 반드시 변수 i가 선언되어야 합니다.**

 

 

2. 포인터는 언제 주로 사용되는가?

함수 인수전달에 사용이 됩니다. 무엇때문에 사용이 될까?라는 의구심이 들었기를 바랍니다.

이는 call-by-referencecall-by-value로 설명을 들 수 있습니다.

call-by-reference는 메모리 주소를 참고할 수 있도록 해당 데이터가 저장된 메모리 주소를 넘기는 방식을 말합니다.

그리고 call-by-value는 데이터자체를 복사해서 넘기는 방식입니다. 이때 call-by-value방식으로 진행을 하면 데이터 크기를 복사하는데 비효율적일때가 있습니다. 이때 효율적으로 하기위해서 call-by-reference를 사용합니다. ex) 배열을 복사하려면 데이터크기가 다른 테이터 타입보다 큽니다. 이때 사용하기도 하고 함수를 넘겨줄 때 사용하기도 합니다.

같은 정보를 반복하지않고 공유하고자 할 때 사용합니다(이러는 경우는 잘 못봤고, 이렇게 해야될 이유가 잘 없습니다.)

 

 

3. 활용은 어떻게 될까?

2번에서 다루었던 주제와 동일합니다. (2번을 요약하는것과 추가적으로 함수포인터와 2차원 배열에 대한 설명으로 3번은 마무리하도록하겠습니다.)  

1.함수 인수전달에 사용이 됩니다.(해당값을 변경하려면 또는 함수가 끝나도 값이 외부에 존재하게 하려고 할때 사용)

2. 같은 정보를 반복하지않고 공유하고자 할 때 사용합니다

=======================================================

(+추가)

3. 배열이름이 포인터라는 점에서 일차원 배열은 이해가 쉬울텐데 2차원배열은 그러면 어떻게 되는걸까?

1차원배열

흔히 알고 있는 1차원배열은 이 그림과 같이 구성이 됩니다.

2차원배열은 행과 열로 구성되어 1차원 배열과 다르다고 생각할 것입니다.

하지만 2차원 배열도 1차원배열로 구성되어있다고 받아들이시면 편합니다.

2차원 배열

즉, numArr[0]부터 2까지 하나의 1차원 배열로 보고 numArr[0~2]하나씩을 또 numArr[0][0]부터3까지구성되어있는 1차원 배열로 보는 것입니다. 

 

다르게 2차원 배열을 생각해보도록하겠습니다.( 사진 출처: dojang.io/mod/page/view.php?id=307 이며 2차원 배열 선언하고 요소에 접근하는 방법을 알려줍니다. 참고하실분은 참고하시면 좋을 듯합니다.)

 

 

4. c언어에서 주의해야할 포인터 개념(   ex) 문자열 => char형 포인터로 구현이 가능하다.   )

c 프로그래밍을 할때 char형 배열로 문자열을 구현하거나, char형 포인터로 구현이 가능합니다. 이러한 점은 java와 파이썬 그외 언어에서 자주 볼 수 없는 경우입니다. 저는 우선 char형 포인터 사용을 추천드립니다. 왜냐하면 java를 배우신 분 String클래스라 생각하시면 이해가 쉽습니다. 다른 객체 지향언어를 접해보신분이라면 String클래스와 연결지어 이해하시면 빠르게 이해할 수 있을 것 같습니다.

reakwon.tistory.com/14

 

[C언어] 문자열과 char 포인터, 문자열을 다룰때 하는 실수들

문자열과 char 포인터 오늘은 심심한데 문자열에 대해서 이야기 해볼까 해요~ 문자열과 포인터는 C언어에서 너무나 귀찮은 놈들인데,,, 그래도 꼭 쓰이니까요 char 자료형은 문자를 변수로 갖는 건

reakwon.tistory.com

위의 링크에서 문자형 배열이름이 포인터임을 항상 숙지를 하며 프로그래밍을 하셔야 실수를 줄일 수 있을 것 같습니다.

위 링크 해당부분

 

 

 

이 글을 읽어 주셔서 감사합니다. 다음에는 파일 입출력과 자료구조(동적메모리, 배열등..)으로 다루며, 진처리 및 다중소스파일과 관련된 내용으로 돌아오겠습니다.

이번 글에서는 저번에 했던 코드에서 회원가입 코드를 보완하겠습니다.

<메인 화면 코드>

package presentation;

import java.util.Scanner;
import valueObject.VPersonalInfo;

public class PMain {

	public PMain() {
	}
	
	public void show() {
		Scanner scanner = new Scanner(System.in);
		
		System.out.println("수강신청 시스템입니다.");
		System.out.println("수강신청을 하려면 로그인 하세요.");
		System.out.println("회원가입이 안되신 분들은 회원가입 하세요.");
		System.out.println("다음 메뉴를 선택 하세요.");
		
		boolean finished = false; 
		while (!finished) {
			System.out.println("1:로그인, 2:회원가입, 3:나가기");
			System.out.println("선택 : ");
		
			int menuSelection = scanner.nextInt();
			if(menuSelection == 1) // 로그인 선택시
           			{ finished = true;} 
            		else if (menuSelection == 2) // 회원가입 선택시
         			{ PRegistration pRegistration = new PRegistration();
			  	  pRegistration.show(scanner);}
           		else if (menuSelection == 3) // 나가기 선택시
          			{ finished = true;}
            		else // 1,2,3이 아닌 다른 수를 선택할 시
        			{ System.out.println("잘못 입력 하셨습니다.");
	}}
		scanner.close();
}}

<회원가입 화면 코드>

package presentation;

import java.util.Scanner;
import service.SRegistration;
import valueObject.VPersonalInfo;

public class PRegistration {	
	
	public void show(Scanner scanner) {
		
		System.out.println("개인정보를 입력하세요.");
		
		VPersonalInfo vPersonalInfo = new VPersonalInfo();
		System.out.print("아이디를 입력하세요.\r\nID:");
		VPersonalInfo.id = scanner.next();
		System.out.print("비밀번호를 입력하세요.\r\n비밀번호:");
		VPersonalInfo.password = scanner.next();
		System.out.print("이름을 입력하세요.\r\n이름:");
		VPersonalInfo.name = scanner.next();
		
        	// 입력한 개인정보 값을 서비스 클래스로 이동
		SRegistration sRegistration = new SRegistration();
		sRegistration.write(vPersonalInfo);
		
		System.out.println("개인정보가 입력되었습니다.");
	}
}

<회원가입 서비스 코드>

package service;

import model.MPersonalInfo;
import valueObject.VPersonalInfo;

	// 위 코드에서 입력받은 정보를 모델 클래스로 이동
	public class SRegistration {
	  public void write(VPersonalInfo vPersonalInfo) {
	    MPersonalInfo mPersonalInfo = new MPersonalInfo();
	    mPersonalInfo.write(vPersonalInfo);
	}
}

<회원가입 모델 코드>

package model;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
import valueObject.VPersonalInfo;

public class MPersonalInfo {

	// 서비스 클래스로부터 받아온 개인정보 값을 파일 형식으로 저장
	public void write(VPersonalInfo vPersonalInfo) {
	   try {
			File file = new File("temp");
			FileWriter fileWriter = new FileWriter(file,true);	
			PrintWriter printWriter = new PrintWriter(fileWriter);
			
			printWriter.println(vPersonalInfo.id);
			printWriter.println(vPersonalInfo.password);
			printWriter.println(vPersonalInfo.name);
			
			printWriter.close();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

<VO(Value Object)>

package valueObject;

public class VPersonalInfo {
	
	public static String id;
	public static String password;
	public static String name;
}

이걸로 회원가입 시스템은 다 만들어봤습니다. 코드에 무언가 문제가 있으시다면 알려주시면 감사하겠습니다.

다음 주부터는 로그인 시스템을 만들어볼 계획입니다.

이번에는 지난번에 공부한 '텍스트 파일 읽고 쓰기'를 바탕으로 시험에 출제되었던 문제를 풀어봤다.

문제는 줄마다 번호를 매기고 그 줄에 해당하는 문자열을 출력하는 것이다.

우선 좋아하는 노래 가사를 넣어 linefile.txt를 작성했다.

위에 문자열들이 '#1: When I was six years old I broke my leg' 이런식으로 출력되게 하기 위해서 코드를 작성했다.

#include<stdio.h>
#define LENGTH 100

int main(void)
{
	int line = 0;
	char str[LENGTH];
	FILE* fp = NULL;

	fp = fopen("linefile.txt", "r");

	while (fgets(str, LENGTH, fp) != NULL) {
		line++;
		printf("#%d: %s\n", line, str);
		if (line == NULL)
			break;
	}
	fclose(fp);

	return 0;
}

결과는 원하는대로 아래와 같이 나왔다.

 

이번에 공부를 하고 다시 이 문제를 풀면서 알게 된 점은 fgets()의 인수를 제대로 이해하지 못하고 있었다는 점인데 이전에는 fgets(fp)로 파일 포인터를 의미하는 fp를 인수로 두고 코드를 작성했었다. 책에 그렇게 나왔었는데 다시 실행시키면서 공부하니까 인수가 조금 달랐다.

fgets()함수를 정리해보면

1. fgets() 함수의 원형은 

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

2. 인수의 내용은

첫 번째, 읽은 문자열이 저장될 주소

두 번째, 읽을 문자의 최대 개수 (이보다 하나 적은 수의 문자를 읽거나, 파일의 끝에 도달할 때까지 문자를 읽음)

세 번째, 스트림을 결정할 FILE 구조체 변수의 포인터

 

3. 이 함수는 읽기에 성공하면 읽은 문자열이 저장된 주소를 반환, 파일의 끝에 도달하거나 읽기에 실패하면 NULL을 반환

4. fgets() 함수는 문자를 읽어 들이는 도중에 개행 문자('\n')를 만나게 되면 곧바로 읽기를 종료(이거는 사실 잘 모르겠음.. 개행 문자 넣어도 읽기가 계속 되던데 연속 두번은 돼야하는 건지...)

5. 지금까지 읽어 들인 문자들이 C언어에서 문자열로 인식되도록 맨 마지막에 널 문자('\0')를 자동으로 추가해 줌

 

그리고 약간 궁금했던게 있었는데 13번째 줄이 비어있어서 12번째 줄까지 출력되고 끝날까 했는데 14번째 줄부터 마지막 줄까지도 계속 출력이 되어서 신기했다. NULL값이 나올 때까지 문자열을 반복해서 출력하는 거니까 13번째 줄은 0으로 처리되지 않았나 싶다.

+ Recent posts