[완료] char** 배열의 원하는 인덱스에 문자열이 제대로 들어가지 않습니다

sacredone의 이미지

제가 질문을 잘 못해서 제가 작성한 코드를 일단 통째로 올려보겠습니다

#include <stdio.h>
#define BUFFER_SIZE 1024
 
int main()
{
	FILE* fp1;
	char* c1 = (char*)malloc(BUFFER_SIZE*sizeof(char));
	char** d_entry = (char**)malloc(sizeof(char*));
	int d_count=0,i;
 
	system("ls -l | grep d > check");
 
	fp1 = fopen("check", "r");
 
	while(fgets(c1, BUFFER_SIZE, fp1) != NULL){
		*(c1+strlen(c1)-1)=NULL;
		puts(c1);
		if(c1[0] =='d'){
			d_entry[d_count] = strtok(c1, " ");
			for(i=0;i<8;i++){
				d_entry[d_count] = strtok(NULL, " ");
			}
			printf("%s is  a directory\n", d_entry[d_count]);
			d_count++;
		}
		else{
			printf("it's a file\n");
		}
	}
 
	printf("%s\n", d_entry[0]);
	printf("%s\n", d_entry[1]);
	system("rm check");
 
	free(c1);
	free(d_entry);
	fclose(fp1);
 
	return 0;
}

이해가 되실지 모르겠습니다

작성한 코드의 목적은

현재 디렉토리에 있는 목록들을

파일과 디렉토리로 구별하고

디렉토리이면 디렉토리 이름을 char** 배열에 삽입하는 것입니다

현재 제 디렉토리 안에는

d1 [디렉토리]
d2.c [파일]
d3 [디렉토리]

이렇게 목록이있어서

d_entry[0] 과 d_entry[1] 를 출력하면

d1
d3
이렇게 찍히고싶은데

실제로 출력해보면
d3
d3
이렇게 출력이되네요

왜그런지 설명해주실수 있으신가요

raymundo의 이미지

strtok() 가 반환하는 토큰들은, 새로 공간을 확보해서 그 주소를 반환하는 게 아니라, 처음에 인자로 받았던 그 문자열 내에서 해당 토큰의 시작지점을 반환하거든요.

check 파일의 각 라인을 읽을 때마다 동일한 공간(c1이 가리키는)에 담고 있기 때문에,
d_entry[0] 이 가리키고 있던 공간도 덮어쓰여 버려서 저렇게 됩니다.

루프 돌 때마다 각 줄을 읽을 공간을 새로 확보해주거나,
그보다는 d_entry[d_count]에 곧바로 strtok()의 반환값을 담지 말고, 새로 malloc()한 후 strcpy로 복사하시면 되겠네요.

좋은 하루 되세요!

sacredone의 이미지

-중략-
 
char* temp;
 
-중략-
 
                   if(c1[0] =='d'){
                        temp = (char*)malloc(sizeof(char));
			temp = strtok(c1, " ");
			for(i=0;i<8;i++){
				temp = strtok(NULL, " ");
			}
                        strcpy(d_entry[d_count], temp);
			printf("%s is  a directory\n", d_entry[d_count]);
			d_count++;
                        free(temp);
		    }
 
-중략-

이렇게 수정해보았는데도 되지를 않네요...

raymundo의 이미지

이 코드는 아까보다 더 문제가 있는 게.... ^^;;

                    if(c1[0] =='d'){
                        temp = (char*)malloc(sizeof(char));       // 이렇게 할당받아봤자
			temp = strtok(c1, " ");                   // 여기서 바로 temp 에 다른 주소가 들어가니까 바로 위에 malloc 받은 건 잃어버리게 되고
			for(i=0;i<8;i++){
				temp = strtok(NULL, " ");
			}
                        strcpy(d_entry[d_count], temp);           // d_entry[d_count] 가 char * 인데, 정작 이 포인터가 가리키는 공간이 아직 없고,
			printf("%s is  a directory\n", d_entry[d_count]);
			d_count++;
                        free(temp);                               // temp 가 현재 가리키는 곳은 c1이 가리키는 공간의 중간 어디쯤이니까 여길 free 하려다간 난리가 날 거고요
		    }

이렇게 고치면 잘 되네요.

    char** d_entry = (char**)malloc(sizeof(char*) * 10);            // 여기도 char * 만큼만 할당받으면 안 되고, 예상되는 디렉토리의 갯수보다 크게 넉넉히 잡아주셔야 하고요,
 
 
 
        if(c1[0] =='d'){
            char * temp;                              // 굳이 여기서 malloc할 필요는 없고
            temp = strtok(c1, " ");
            for(i=0; i<8; i++) {
                temp = strtok(NULL, " ");
            }
            d_entry[d_count] = (char *) malloc( strlen(temp) + 1 );    // 할당받은 후에 strcpy
            strcpy(d_entry[d_count], temp);
 
            /* 아니면 temp 를 쓸 필요도 없이 이렇게 하셔도 될 듯
            strtok(c1, " ");
            for(i=0;i<7;i++){              // 8 대신 7로 줄이고, strtok() 반환값은 필요없으니 날린 후에
                strtok(NULL, " ");
            }
            d_entry[d_count] = (char *) malloc(20);   // 대신 여기에선 넉넉히 20글자 들어가게 잡았음
            strcpy(d_entry[d_count], strtok(NULL, " "));    // 여기서 마지막 strtok()
            */
 
            printf("%s is  a directory\n", d_entry[d_count]);
            d_count++;
        }
 
// free 하는 곳도
    for (i=0; i<d_count; i++) {    // 각 원소가 가리키는 공간 먼저 해제해 주셔야 깔끔
        free(d_entry[i]);
    }
    free(d_entry);
    fclose(fp1);

좋은 하루 되세요!

sacredone의 이미지

codre dump 가 일어나긴 하는데

대충 뭐가문제인지 감이오네요

제가지금 문자열에 대한것과 포인터에 대한 이해가

100%가 아닌거같습니다

막연히 대충 어떻게 되는것만 알고있지

정확하진 않은거같네요

제가지금 인턴중인데

회사에서 과제로 몇개 내주는거 짜보고있는데

문제가 많은거같습니다 ㅠㅠ

시간되시면...

나중에 제가짠거 전체적으로 봐주실수있을까요..

raymundo의 이미지

엥, 제가 적은 코드로 코어덤프가 난다는 말씀이신가요? valgrind 까지 돌려봐서 에러 없는 거 확인하고 올린건데...

뭐 암튼, 저야 아직 모르는 게 많습니다만, 나중에라도 여기 올리시면 다른 고수님들께서도 같이 봐주시겠지요... :-)

좋은 하루 되세요!

sacredone의 이미지

짜주신게 free 까진데

제가 그뒤에 free 한 부분을 참조할려는 코드가있었던걸 깜빡했네요

core dump 일어나지않고 깔끔합니다

정말 감사합니다

공부를 많이해야겠습니다 ..

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.