c언어에서 파일에서 한줄씩 단어를 읽어올때 숫자와 문자열을 구별해 주는 방법

quarterhorse의 이미지

파일에서 한줄씩 단어를 읽어서, 해당 단어가 숫자일 경우와 문자일경우, 그리고 아무것도 아닌 경우를 나눠서

동작하는 프로그램을 연습해 보고 있습니다. 생각한 방법은, fopen을 통해 파일을 불러오고,

fscanf를 통하여 단어를 읽어와, str 배열에 저장한 뒤에, 이걸 꺼내와서

1. 숫자일 경우

2. 문자일 경우

3. 아무것도 아닐 경우

로 분기하여, 경우별로 기능이 동작하고,

완료 되면 다음 단어와 다음 줄을 찾아 계속 반복, EOF (파일의 끝)이 나오면 종료되는 코드를 짜보려고 했습니다.

시험삼아서, if, else if, else 부분에 isdigit같은 숫자 판별 함수를 사용해 봤는데, 역시 동작하지 않습니다.

아마 제가 생각한 판별 방식이 틀린거 같은데,

위 3가지 경우를 판별할 수 있는 방법을 알려주신다면 정말 감사드리겠습니다 ... ㅠㅠ

아래 코드는 그냥 대충 제가 짜본 코드입니다.

#include <stdio.h>
#include <string.h>
 
char str [100];
 
int c;
 
void main()
{
	// 파일 읽기 위한 준비
	FILE *fp;
 
	fp = fopen("c:\\testfile.txt","r");
 
	if(fp==NULL)
	{
		printf("이 파일은 존재하지 않습니다\n");
	}
	else
	{
		c=getc(fp);
		while(c!=EOF){
                                                // 파일에서 단어를 읽어와 str 배열에 저장한다
						fscanf (fp, "%s", str);
						// 숫자일 경우
						if()
						{
							printf(" 이건 숫자다...\n");
							c=getc(fp);
						}
						// 문자열일 경우
						else if()
						{
							printf(" 이건 문자열이다\n");
							c=getc(fp);
						}
						// 아무것도 아닌 경우
						else
						{
						printf("이것은 아무것도 해당이 되지 않는다\n");
						c=getc(fp);
						}
		}
		fclose(fp);
	}
}
<code>
qiiiiiiiip의 이미지

c=getc(fp)가 오동작을 일으킬 것 같네요..

while ( fscanf( fp, "%s", str ) == 1 )
{
if ( isnum(str) ) ...
else
}

식으로 해보시지요.
( 이코드는 한줄씩 동작하지 않습니다. 한 단어(공백기준)씩 동작합니다..)

isdigit은 한글자씩 확인하는 함수입니다.
strtod 류의 함수를 쓰서 문자열의 끝까지 변환이 됐는지 확인하면 isnum 함수는 구현이 될것 같네요.
그런데 숫자도 아니고 문자열도 아닌것은 어떤것을 의미하나요??

그리고 어떻게 했는데 어떻게 안되더라도 꼭 같이 적어주세요..

quarterhorse의 이미지

제가 생각했을땐 숫자도 아니고 문자도 아닌것을 특수문자나 기호같은걸 처리받으려고 했구요

is digit부분을 if, 알파뱃 부분을 ASCII코드값으로 받아와 else if, 나머지를 else로 주려고 했었습니다.

에고 그리고 c=gets가 줄단위가 아니고 공백 인식이였는데 제가 잘못 적어뒀습니다... 으으 ㅠㅠ

알려주신 방법대로 한번 해보았는데, char*형식의 인수가 int 형식의 매개변수와 호환되지 않습니다라는 에러가 발생합니다....

아마 제가 *char로 선언해서 발생하는 문제인거 같은데, 읽어올 파일이 영단어와 숫자가 혼용이 되어서 저렇게 받아뒀었습니다...

도와주셔서 감사합니다!

shint의 이미지

#include <stdio.h>
#include <string.h>	//strlen memset
#include <ctype.h>	//isalpha isdigit
 
char str [100];
 
//모두 문자면 찾은 갯수.
//문자가 아닌게 있으면. -1
int fn_isString(char* str)
{
	int cnt = 0;
	int len = strlen(str);
	if(len == 0)
	{
		return -1;
	}
 
	for(int i=0; i<len; i++)
	{
		//문자
		int n = isalpha( *(str+i) );	//0이 아니면 문자
		if( n != 0 )
		{
			cnt++;
		}
	}
 
	if(len == cnt)
	{
		return cnt;
	}
	return -1;
}
 
//모두 숫자면 찾은 갯수.
//숫자가 아닌게 있으면. -1
int fn_isNumber(char* str)
{
	int cnt = 0;
	int len = strlen(str);
	if(len == 0)
	{
		return -1;
	}
 
	for(int i=0; i<len; i++)
	{
		//숫자
		int n = isdigit( *(str+i) );	//0이 아니면 숫자.
		if( n != 0 )
		{
			cnt++;
		}
	}
 
	if(len == cnt)
	{
		return cnt;
	}
	return -1;
}
 
 
void main()
{
 
	// 파일 읽기 위한 준비
	FILE *fp = NULL;
	fp = fopen("testfile.txt","r");
	if(fp==NULL)
	{
		printf("이 파일은 존재하지 않습니다\n");
	}
	else
	{
		while(1)
		{
			memset(str, '\0', sizeof(str));
			if(fgets(str, 100, fp) == NULL)
				break;
 
			//한줄씩 읽는다.
			//fgets는 \n까지 얻는다. 맨 마지막 \n를 제거해준다.
			int max_len = strlen(str);
			if(max_len > 0)
			{
				str[max_len-1] = '\0';
			}
 
 
//			//스페이스가 구분자가 되어. 한줄에서 여러번 읽어질 수 있다.
//			//fgets와는 다르게 문자열 단위로 읽는다.
//			int max_len = fscanf (fp, "%s", str);
//			if(max_len == -1)
//				break;
 
			// 숫자일 경우
			int n1 = fn_isNumber(str);
			if( n1 >= 0 )
			{
				printf(" 이건 숫자다... %s\n", str);
				continue;
			}
 
			// 문자열일 경우
			int n2 = fn_isString(str);
			if( n2 >= 0 )
			{
				printf(" 이건 문자열이다 %s\n", str);
				continue;
			}
 
			if(n1 == -1 && n2 == -1)
			{
				printf("이것은 아무것도 해당이 되지 않는다 %s\n", str);
			}
		}
		fclose(fp);
	}
}

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

quarterhorse의 이미지

위 부분의 isalpha, isdigit를 이렇게 구현해주면 되는군요...

마지막에 문자열 처리 부분도 잘 봤습니다.

하지만 실제로 파일을 읽어오력고 하니 에러가 납니다...

아마 char형식의 배열에 저장해둔 혼합된 문자열을 빼오면서 비교할때 캐스팅연산 부분쪽에 문제가 있는거 같기도 한데...

못잡겠네요 ㅠㅠ

아무튼 바쁘신 시간 쪼개서 도와주셔서 감사합니다!!

댓글 첨부 파일: 
첨부파일 크기
Image icon 12312312323.png30.44 KB
raymundo의 이미지

문제를 좀 애매하게 적으셔서...

"한 줄씩 단어를 읽는다"는 건 한 줄에 한 단어만 있다는 뜻인지, 한 줄에 여러 단어가 있다면 한 줄씩 읽겠다는 건지 한 단어씩 읽겠다는 건지 모르겠고,

또 보통 "문자"라고 하면 char 하나를 문자라고 부르니까 '1'도 'a'도 '@'도 다 문자이죠.
"단어가 문자인 경우"는 아마 단어를 구성하는 문자 모두가 알파벳인 경우를 말씀하시는 것 같은데
"abc"는 문자인 경우고 "123"은 숫자인 경우라면 "ab123"은 뭐에 해당되는지 모르겠네요.

그래서 제 맘대로
- 한 단어씩 읽고
- 단어를 구성하는 문자들 모두가 알파벳인 경우, 모두가 숫자인 경우, 그 외의 경우, 이렇게 세 가지로 나눔
으로 가정했습니다. :-)

일단 본문에 쓰신 코드는 제일 처음에 getc 를 한 번 불러버리니까, 파일의 제일 첫 단어가 "1abc"라면 1은 getc가 읽어버리고 fscanf 는 "abc"만 읽을 겁니다. 제대로 판정되지 않겠네요. 두번째부터는 getc는 어차피 공백문자를 읽을 테니 큰 상관은 없겠지만요.

이건 qiiiiiiiip님께서도 말씀하셨듯이

        while( fscanf(fp, "%s", str) > 0 ) {    // fscanf 를 하고 그 반환값으로 루프 반복 여부를 결정하고
           if( is_num(str) )
            {
                printf(" 이건 숫자다...\n");
            }
            // 문자열일 경우
            else if( is_word(str) )
 
        }

형태로 하시면 될 거고,

그리고 is_num()이나 is_word()는 단어 전체가 숫자들 또는 알파벳만으로 있는 경우만 참을 반환하기로 하면

int is_word( char * s ) {
    while ( *s != '\0' ) {
        if ( !isalpha(*s) ) {    // is_num()이라면 여기는 isdigit()로
            return 0;   // 한 글자라도 조건에 맞지 않는 문자가 발견되면 거기서 그냥 리턴하면 되죠, 굳이 루프 더 돌아볼 것 없이.
        }
        s++;
    }
    return 1;
}

이렇게 하면 되겠군요.

그리고 "알려주신 방법대로 한번 해보았는데"라는 말은, 그 알려주신 방법이 전체 코드가 적혀 있었다면 모를까, 전혀 힌트가 안 됩니다.
뭔가 잘못되어 있으니까 에러가 났을텐데 그 뭔가를 찾으려면 코드를 봐야죠. 답변하는 사람 입장에서는 더 말을 할 수가 없는 상태가 됩니다. :-)

좋은 하루 되세요!

qiiiiiiiip의 이미지

String 이 숫자이다, 또는 문자이다 라는 말은 프로그래머의 용어가아니죠.

그 정의부터하고 문제를 풀어야합니다.

-1, 3.1415, 1e+2, .123, -12. 이건 숫자가 아닌가요?

ab_cd, can't, 개미, b2b 이건 문자가 아닌가요?

shint의 이미지

그 상황에 맞는. 정형화된 데이터 규칙이 있어야 할거 같습니다.
모두 처리할 수 있는 함수를 만들기는 어려워 보입니다.

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

quarterhorse의 이미지

알려주신 코드 구성방식과 지적해주신 부분들은 다시 한번 곰곰히 생각해 봐야겠습니다.

자세한 답변 정말로 정말로 모두 감사드립니다... ㅜㅜ

좋은주말되세요!

댓글 달기

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