[질문]다음 C프로그램에서 잘못된 부분이 있나요?

keston의 이미지

원래 소스가 길어서 핵심부분만 뽑아서 질문 드립니다.

main(int argc,char **argv) 
{
int flag=1;
char *name=(char *)malloc(100);
char *pass=(char *)malloc(100);
FILE *fp;

fp=fopen("log","r");
while(!feof(fp)) {
fscanf(fp,"%s\t%s\n",name,pass);
if(!strcmp(argv[1],name) && !strcmp(argv[2],pass)) flag=0;
}
fclose(fp);
free(name);
free(pass);

if(flag==1) {
fp=fopen("log","a");
fprintf(fp,"%s\t%s\n",argv[1],argv[2]);
fclose(fp);
}
}

argv로 받은 값중에서 이미 log파일에 기록된거면 기록이 안되야 하는데 log파일을 열어보면 중복되서 기록이 되어 있습니다.
왜 이런 현상이 발생하는 걸까요?
이한길의 이미지

오랫만에 C언어 코드를 보니깐... 조금 확신이 안서긴 하지만..
다음을...

fscanf(fp,"%s\t%s\n",name,pass);

이렇게 고쳐야 하는것 아닌가요?

fscanf(fp,"%s\t%s\n",&name,&pass);

저는 그렇게 생각하는데 아닌지도 모르겠습니다.
scanf보다 getc로 하나씩 읽어다 담는게 편합니다.

i=0;
while((ch=fgetc(fp))!='\t') name[i++]=ch;
name[i+1]=0;

이런 식으로 말이지요...

----
먼저 알게 된 것을 알려주는 것은 즐거운 일이다!
http://hangulee.springnote.com
http://hangulee.egloos.com

onemind555의 이미지

별다른 내용은 없는데 꽤 복잡 하게 되어 있네요...

잘 모르겠네요.. 얼핏 보기에는 별 문제 없어 보이는데... 소스를 좀 쉽게 고치면 답이 보일 겁니다...

그리고 flag를 고쳤으면 break해서 빠져 나가야죠...

-----------^^ ^^ ^^ ^^ ^^ ----------
..........................................................

버려진의 이미지

일단 직접 컴파일 해서 해봤는데 문제 없었습니다.
onemind님께서 말씀하신 것처럼 해서 좀더 효율성을 높일 수 있고, fp가 NULL인지 체크해야 하고 ... 같은건 있지만 여튼 원하시는 대로 동작합니다.

그리고 저라면 malloc을 안하고 그냥 배열로 할것 같군요 :)

정태영의 이미지

이한길 wrote:
오랫만에 C언어 코드를 보니깐... 조금 확신이 안서긴 하지만..
다음을...

fscanf(fp,"%s\t%s\n",name,pass);

이렇게 고쳐야 하는것 아닌가요?

fscanf(fp,"%s\t%s\n",&name,&pass);

저는 그렇게 생각하는데 아닌지도 모르겠습니다.

헤헷.. 제가 보기엔 저부분은 맞는거 같네요 ;)
=3=333

name하고 pass값을 찍어보면서 디버깅해보세요 슈슝

if(!strcmp(argv[1],name) && !strcmp(argv[2],pass)) flag=0; 

#define DEBUG

#ifdef DEBUG
  fprintf( stderr, "DEBUG: %s, %s, %s, %s\n", argv[1], name, argv[2], pass );
#endif

if(!strcmp(argv[1],name) && !strcmp(argv[2],pass)){

    flag=0; 
    break;
}

저같음 저렇게 =3=33

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

jemiro의 이미지

name, pass를 초기화 시켜주고
fscan의 format스트링을 아래와 같이 고치면 좀더 확실할것 같습니다.

int main(int argc,char **argv) 
{
int flag=1;
FILE *fp;
char *name=(char *)malloc(100);
char *pass=(char *)malloc(100);

fp=fopen("log","r");
while(!feof(fp)) {
memset(name, 0, 100);
memset(pass, 0, 100);
fscanf(fp, "%[^\t]\t%[^\n]\n", name, pass);
if(!strcmp(argv[1],name) && !strcmp(argv[2],pass)) flag=0;
}
fclose(fp);
free(name);
free(pass);

if(flag==1) {
fp=fopen("log","a");
fprintf(fp,"%s\t%s\n",argv[1],argv[2]);
fclose(fp);
}
}
alwaysrainy의 이미지

char *name=(char *)malloc(100);
char *pass=(char *)malloc(100);

저는 이상없이 작동하는데요.. 이상하군요.. 일부 소스라고
하셨는데요.. 배열대신 name과 pass를 동적으로 할당해서
사용하는 목적이 다른 함수내에서 참조가 가능케 하기
위함인가요? 혹시라도 그렇다면.. 그 함수의 소스코드도
올려주셔야 할 듯 한데요.. 애매하군요.. ^^

---------------------------------------
세계는 넓고, 할일은 많다.

ㅡ,.ㅡ;;의 이미지

Quote:

오랫만에 C언어 코드를 보니깐... 조금 확신이 안서긴 하지만..
다음을...

코드:
fscanf(fp,"%s\t%s\n",name,pass);

이렇게 고쳐야 하는것 아닌가요?

코드:
fscanf(fp,"%s\t%s\n",&name,&pass);

저는 그렇게 생각하는데 아닌지도 모르겠습니다.

일단 이거은요 기존것이 맞죠. 자체가이미 주소니까요.

그리고 scanf 류.. 잘안쓰는데..문자를 읽은다음에 보이지않는특수문자가 붙어오지 않는다면 정상으로 될것같네요
님이 사용하시는 데이터파일 로 비교하시는중간에 값들을 출력해보세요.


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

이한길의 이미지

정태영 wrote:
이한길 wrote:
오랫만에 C언어 코드를 보니깐... 조금 확신이 안서긴 하지만..
다음을...

fscanf(fp,"%s\t%s\n",name,pass);

이렇게 고쳐야 하는것 아닌가요?

fscanf(fp,"%s\t%s\n",&name,&pass);

저는 그렇게 생각하는데 아닌지도 모르겠습니다.

헤헷.. 제가 보기엔 저부분은 맞는거 같네요 ;)
=3=333

아핫! 그런가요? 포인터를 사용했을 경우는 그대로 전달하고...
배열 선언해서 한 경우에 그렇게 해야 하는거였던가요?
ㅜㅜ;

감솨합니다...

----
먼저 알게 된 것을 알려주는 것은 즐거운 일이다!
http://hangulee.springnote.com
http://hangulee.egloos.com

맹고이의 이미지

이한길 wrote:

아핫! 그런가요? 포인터를 사용했을 경우는 그대로 전달하고...
배열 선언해서 한 경우에 그렇게 해야 하는거였던가요?
ㅜㅜ;

감솨합니다...

배열도 마찬가지입니다.

정태영의 이미지

이한길 wrote:
아핫! 그런가요? 포인터를 사용했을 경우는 그대로 전달하고...
배열 선언해서 한 경우에 그렇게 해야 하는거였던가요?
ㅜㅜ;

감솨합니다...

int, char, float, double, short, long, ... 등일 때는.. & 주소값으로 넘겨주고..
포인터인 경우 원래 주소값을 가지니 =3=33 그럴 필요가 없어지죠..

char aaa[20]; 식으로 선언하면.. aaa는 상수포인터가 되는거구요 =3=33
(결과적으로 포인터로 선언하나 배열로 선언하나 두가지는 똑같이 사용할 수 있습니다..)

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

keston의 이미지

많은 답변 감사합니다.^^

jemiro wrote:

memset(name, 0, 100);
memset(pass, 0, 100);
fscanf(fp, "%[^\t]\t%[^\n]\n", name, pass);

아..제가 변수 초기화 해주는걸 잊었네요..
근데 저기서 초기화 해주는 거랑 않해주는 거랑 차이가 있을까요?
(딴지 거는건 아니구요..제가 아직 초보라서 잘 몰라서요..^^)
그리고 아래 fscanf()에 들어가는 포맷이 전 처음 보는 거네요..
무슨 뜻인가요??

현재까지 중복기록되는 경우는 2가지인데..
1. log에 많이 쌓인 경우
wc 명령어로 보니 370바이트가 넘어가면서 부터 중복 기록됩니다.
2. argv로 받은 값중에 공백(스페이스)이 있는 경우
즉 aaa[탭]123[공백]456 이런식으로 값이 들어오면 중복기록되 있습니다.

근데 제가 sort와 uniq 명령어로 보던 중 이상한 점이 있어 또 질문드립니다.^^
cat log
a 1
b 2
a 1

uniq log
a 1
b 2
a 1

sort -u log
a 1
b 2
제가 생각하기엔 이 두 명령의 결과가 같아야 하는걸로 알고 있는데 다르게 나오네요..
혹시 이거랑 위에서 질문한 로그에 중복 기록되는 거랑 연관이 있을까요?

정태영의 이미지

keston wrote:

2. argv로 받은 값중에 공백(스페이스)이 있는 경우
즉 aaa[탭]123[공백]456 이런식으로 값이 들어오면 중복기록되 있습니다.

argv는.. 공백으로 구분해서 갈릴텐데.. argv로 받은값에.. 공백이 들어갈 수 있는지 알수가 없군요 =3=33

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

keston의 이미지

정태영 wrote:

argv는.. 공백으로 구분해서 갈릴텐데.. argv로 받은값에.. 공백이 들어갈 수 있는지 알수가 없군요 =3=33

아..위에 올린 소스는 제가 임의로 만든거구요..
실제 소스에선 로그에 기록되는 값을 argv로 받지 않습니다.
즉 공백이 들어갈수 있습니다.
제가 이부분은 미처 생각하지 못하구 질문 올렸네요..ㅡㅡ;
정태영의 이미지

keston wrote:
근데 제가 sort와 uniq 명령어로 보던 중 이상한 점이 있어 또 질문드립니다.^^
cat log
a 1
b 2
a 1

uniq log
a 1
b 2
a 1

sort -u log
a 1
b 2
제가 생각하기엔 이 두 명령의 결과가 같아야 하는걸로 알고 있는데 다르게 나오네요..
혹시 이거랑 위에서 질문한 로그에 중복 기록되는 거랑 연관이 있을까요?

우선.. 이건..
cat log | sort | uniq

하면 같은 결과 아닌가요 ;)
유니크는.. 연속해서 같은게 나올때만 걸렸던거 같은데 ..

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

정태영의 이미지

keston wrote:
많은 답변 감사합니다.^^
jemiro wrote:

memset(name, 0, 100);
memset(pass, 0, 100);
fscanf(fp, "%[^\t]\t%[^\n]\n", name, pass);

아..제가 변수 초기화 해주는걸 잊었네요..
근데 저기서 초기화 해주는 거랑 않해주는 거랑 차이가 있을까요?
(딴지 거는건 아니구요..제가 아직 초보라서 잘 몰라서요..^^)
그리고 아래 fscanf()에 들어가는 포맷이 전 처음 보는 거네요..
무슨 뜻인가요??

흠.. fscanf는 모르겠지만..
strncpy나.. 뭐 몇가지 함수들의 경우.. 뒤에.. \0을 붙여주지 않기 때문에..
;) 문제가 되기도 합니다..

근데.. fscanf를 써야 하는 이유가 있나요?
fgets로 한라인씩 받으면서.. strcmp는 한번씩만 하는게 더 나을 듯 한데요 :)

keston wrote:
while(!feof(fp)) {
fscanf(fp,"%s\t%s\n",name,pass);
if(!strcmp(argv[1],name) && !strcmp(argv[2],pass)) flag=0;
}

이걸..

#define MAX_SIZE 255

char namemixedpass[MAX_SIZE+1];
char buf[MAX_SIZE+1];

int len;

sprintf( namemixedpass, "%s\t%s\n", name, pass );
len = strlen( namemixedpass );

while( !feof(fp) ){

    fgets( buf, MAX_SIZE, fp );
    if( !strncmp( buf, namemixedpass, len ) ){
        flag = 0;
        break;
    }

}

가 더 나을듯 하군요 =3=33
(근데 fgets로 받으면 뉴라인이 버퍼에 들어가던가 안들어가던가 =3=33);;;

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

댓글 달기

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