[질문]C에서 StringBuffer의 구현은 어떻게?

lhuijae의 이미지

자바에서는 StringBuffer가 있고, C++에서 string 클래스에는 append() 메소드가 있어서 문자열을 쉽게 추가시킬수 있잖아요.. 이런걸 스트링벡터, 스트링버퍼? 라고 하나요? 하여튼..

C에서 이 기능을 사용하고 싶은데 어떻게 구현을 해야할지 모르겠습니다. 제가 하고싶은것은 파일을 한줄씩 읽어서 파일의 내용을 버퍼에 저장하고 싶은데 파일의 크기만큼 충분한 문자열 버퍼를 만든다음 읽어들인것들을 차례로 추가시켜도 되겠지만 저런 자바나, C++에서와같은 편리한 기능이라고 해야할까요? 그걸 구현해보고 싶은데.. 어떻게 해야할지..

madhatter의 이미지

char type pointer 랑 sprintf 쓰시면 되지 않을까요..

feanor의 이미지

realloc을 쓰셔야 할 것 같은데요.

--feanor

ㅡ,.ㅡ;;의 이미지

lhuijae wrote:
자바에서는 StringBuffer가 있고, C++에서 string 클래스에는 append() 메소드가 있어서 문자열을 쉽게 추가시킬수 있잖아요.. 이런걸 스트링벡터, 스트링버퍼? 라고 하나요? 하여튼..

C에서 이 기능을 사용하고 싶은데 어떻게 구현을 해야할지 모르겠습니다. 제가 하고싶은것은 파일을 한줄씩 읽어서 파일의 내용을 버퍼에 저장하고 싶은데 파일의 크기만큼 충분한 문자열 버퍼를 만든다음 읽어들인것들을 차례로 추가시켜도 되겠지만 저런 자바나, C++에서와같은 편리한 기능이라고 해야할까요? 그걸 구현해보고 싶은데.. 어떻게 해야할지..

미리 array를 잡든 memory realloc 을하든 링크드리스트를사용하든 목적에 따라 구현할수 있겠지만. 일반적으로 그러한방식은 시간적으로나 공간적으로나
낭비가되기 쉽습니다. 사용할지 안할지도 모르는데 미리부터 다읽어들이면 낭비죠.


----------------------------------------------------------------------------

Jun92의 이미지

MFC의 CString 클래스에서는 realloc를 쓰더군요.

=============================
야후!

낙엽의 이미지

애디슨 웨슬리에서 나온 C interfaces and implementation 이라는 책이 있습니다.

15장, 16장 Low-level string, High-level string 부분을 참조하세요..

eungkyu의 이미지

ㅡ,.ㅡ;; wrote:
lhuijae wrote:
자바에서는 StringBuffer가 있고, C++에서 string 클래스에는 append() 메소드가 있어서 문자열을 쉽게 추가시킬수 있잖아요.. 이런걸 스트링벡터, 스트링버퍼? 라고 하나요? 하여튼..

C에서 이 기능을 사용하고 싶은데 어떻게 구현을 해야할지 모르겠습니다. 제가 하고싶은것은 파일을 한줄씩 읽어서 파일의 내용을 버퍼에 저장하고 싶은데 파일의 크기만큼 충분한 문자열 버퍼를 만든다음 읽어들인것들을 차례로 추가시켜도 되겠지만 저런 자바나, C++에서와같은 편리한 기능이라고 해야할까요? 그걸 구현해보고 싶은데.. 어떻게 해야할지..

미리 array를 잡든 memory realloc 을하든 링크드리스트를사용하든 목적에 따라 구현할수 있겠지만. 일반적으로 그러한방식은 시간적으로나 공간적으로나
낭비가되기 쉽습니다. 사용할지 안할지도 모르는데 미리부터 다읽어들이면 낭비죠.

무슨소리인지 모르겠어요 :(

그래서 array, memory realloc, 링크드리스트 모두 시간적으로나 공간적으로나 낭비가 있기 때문에 쓰지 말아야 한다는 것인가요?

그럼 어떻게 해야 하나요?

ㅡ,.ㅡ;;의 이미지

eungkyu wrote:

무슨소리인지 모르겠어요 :(

그래서 array, memory realloc, 링크드리스트 모두 시간적으로나 공간적으로나 낭비가 있기 때문에 쓰지 말아야 한다는 것인가요?

그럼 어떻게 해야 하나요?

말그대로요 그래서 필요한만큼읽어서 처리하고더필요하면 더읽어오면되겠죠

그렇다해서 꼭필요한곳에도 쓰지말라는말이 아니고요.어떤특이한곳에는 있을수 있겠죠..아마도 스트링그대로를 그렇게 전체를 읽어두고 써야할필요성이 있겠나 싶은데 대부분 필요한만큼읽어서 구조체배열이나 이런곳에 순차적으로 저장하면서 구조체배열등을 추가해나가겠죠..단순히 스트링을 메모리에 적제해서는 어떠한 자료처리를 그대로 하기곤난하기때문에 다시 또다른메모리등으로 작업이 이루어져야 하는데 그럴꺼면 첨에 전체를 읽지말고 필요한만큼읽어서 구조체에 적제하거나 바로 처리하는형식이더 낫겠죠..


----------------------------------------------------------------------------

eungkyu의 이미지

ㅡ,.ㅡ;; wrote:
eungkyu wrote:

무슨소리인지 모르겠어요 :(

그래서 array, memory realloc, 링크드리스트 모두 시간적으로나 공간적으로나 낭비가 있기 때문에 쓰지 말아야 한다는 것인가요?

그럼 어떻게 해야 하나요?

말그대로요 그래서 필요한만큼읽어서 처리하고더필요하면 더읽어오면되겠죠

이 말이 없어서 헷갈리고 있던 거 같네요 :)
전 낭비없이 읽을 수 있는 다른 방법이 있다고 하시는 줄 알았습니다

물론 한번에 읽어서 처리해야 할 양이 정해져 있고, 그리 크지 않다면 이렇게 처리하면 되겠지만, 텍스트를 줄단위로 읽는 것처럼 크기가 정해져있지 않을 때에는 어떻게든 동적으로 할당을 해서 읽는 것이 낳겠죠.

Quote:
그렇다해서 꼭필요한곳에도 쓰지말라는말이 아니고요.어떤특이한곳에는 있을수 있겠죠..아마도 스트링그대로를 그렇게 전체를 읽어두고 써야할필요성이 있겠나 싶은데 대부분 필요한만큼읽어서 구조체배열이나 이런곳에 순차적으로 저장하면서 구조체배열등을 추가해나가겠죠..단순히 스트링을 메모리에 적제해서는 어떠한 자료처리를 그대로 하기곤난하기때문에 다시 또다른메모리등으로 작업이 이루어져야 하는데 그럴꺼면 첨에 전체를 읽지말고 필요한만큼읽어서 구조체에 적제하거나 바로 처리하는형식이더 낫겠죠..
lhuijae의 이미지

친절하게 답변달아주셔서 감사합니다.. 자바의 StringBuffer의 append() 메소드 코드를 봤는데 거의 같은 식이더군요.. 일단 최소한의 공간을 잡아놓고 필요할때 다시 재 할당하고.. 그래서 realloc 함수를 사용해서 해결했습니다.. ㅎㅎ

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static char *str[3] = 
{
    "Linux is a free Unix-type operating system originally created by Linus Torvalds ",
    "Then Linux Online's classroom can help! ",
    "Comprehensive information and resources about the Linux Operating System"
};

int
main(void) {
    char *buf = NULL;
    int i, cur, before;

	for (i = 0, cur = 0, before = 0; i < 3; i++) 
	{
		cur = strlen(str[i]) + 1;

		buf = (char *)realloc(buf, before + cur);
		strncat(buf, str[i], cur);

		before = cur;
	}

    printf("%s\n", buf);

    return 0;
}
eungkyu의 이미지

한가지만 더하겠습니다. realloc으로 크기를 바꿀 때 너무 자주 잘게 크기를 늘리면 무시하지 못할 만큼의 오버헤드가 생깁니다. 예를 들어 하나 받을때마다 하나 크게 해서 realloc을 하면 10000개 받을 때는 realloc을 10000번 해줘야겠죠 :(

그렇게 해서 생각할 수 있는게 한번에 많이씩 늘리는 방법이 있습니다. 크기를 늘릴 때 100씩 늘린다고 하면 최악의 경우 100의 메모리는 낭비하겠지만, realloc 회수는 100으로 줄겠죠.

저같은 경우는 두배씩 늘리는 방법을 애용합니다. 초기 크기를 8이나 16정도로 하고 넘칠 때마다 크기를 두배씩 늘리죠. 가면 갈수록 낭비하는 메모리가 커질 수 있지만, 그러면 규모도 그만큼 커진 상태이니까 큰 영향이 없을 거라고 생각합니다. 이 방법이 규모를 정확히 알 수 없을 때 적절히 쓰일만 한 것 같습니다 :)

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.