2017-02-17 1 views
0

데이터베이스의 두 항목의 성과 이름을 변경하기 위해 두 문자열을 읽는 다음과 같은 방법이 있습니다. 이름은 항상 소문자로 변환되며 하이픈이 문자열의 첫 번째 또는 마지막 문자가 아닌 경우 문자 또는 하이픈이있는 이름 만 가져야합니다. 오류가 발생하면 사용자에게 다시 묻습니다.내 C 코드의 논리 오류

/* 
Prompts for a student name, and checks if input is correct. 
Returns 0 on success, -1 onEOF. 
If the user inputs an invalid entry, the error is ignored and the user is simply asked again. 
*/ 
int get_name(char *first, char *last) 
{ 
char input[LINESIZE]; 
char buffer[LINESIZE]; 
char buffer2[LINESIZE]; 
int i; 

while (1) 
{ 
    printf("\n%s", "Enter the Student Name "); 
    if (!fgets(input, LINESIZE, stdin)) 
    { 
     clearerr(stdin); 
     return -1; 
    } 
    if (sscanf(input, "%s %s", buffer, buffer2) == 2) 
    { 
     if (strlen(buffer) < 20 && strlen(buffer2) < 20 && strlen(buffer) >= 2 && strlen(buffer2) >= 2) /*checks to see if the length is at least 2, but less than 20*/ 
     { 
      for (i = 0; i < 20; i++) /*checks every character on the string, converts it to lower and then checks if it's a letter or a hyphen, restarts if not.*/ 
      { 
       if (isalpha(buffer[i])) 
       { 
        buffer[i] = tolower(buffer[i]); 
       } 
       if (isalpha(buffer2[i])) 
       { 
        buffer2[i] = tolower(buffer2[i]); 
       } 
       if (!isalpha(buffer[i]) && buffer[i] != '-') 
       { 
        break; 
       } 
       if (!isalpha(buffer2[i]) && buffer2[i] != '-') 
       { 
        break; 
       } 
      } 
      if (buffer[0] == '-' || buffer[(strlen(buffer) - 1)] == '-') 
      { 
       i = 0; 
      } 
      if (buffer2[0] == '-' || buffer2[(strlen(buffer2) - 1)] == '-') 
      { 
       i = 0; 
      } 
      if (i == 20) 
      { 
       sscanf(buffer, "%s", first); 
       sscanf(buffer2, "%s", last); 
       return 0; 
      } 
     } 
    } 
} 

}

나는 (!isalpha(buffer[i]) && buffer[i] != '-')와 라인에 오류를 추적했지만 문이 잘못된 이유를 알아낼 수 없습니다.

예를 들어, 성공적인 입력은 "john smith"또는 "hom-er simpson"이 될 수 있습니다. 이 두 경우 모두 함수는 0 (성공)을 반환해야합니다. 입력 내용이 "Denny 's White", "-alexa redfield", "albert"또는 "1234 5647"인 경우 함수를 다시 시작해야합니다 (사용자에게 다시 묻습니다). 현재 입력에 관계없이 함수가 다시 시작됩니다.

+1

는 예를 들어 입력, 의도 된 출력과 실제 출력을 보여주십시오. –

+0

주석이 없으면이 코드의 어떤 부분을 의도하는지 알기가 정말 어렵습니다. 예를 들어'i'가 20에 도달하면 테스트하는 이유는 무엇입니까? 그게 뭐라고 생각하니? 그리고 마지막 두 번의 scanf 호출이 어떻게 생각하십니까? 두 개의 'break'문장의 의도 된 목적은 무엇입니까? –

+0

내 나쁜, 더 많은 의견을 추가하려면 게시물을 편집합니다. 문자열의 각 문자가 문자 또는 하이픈이 아닌지 확인하기 위해 for 루프를 사용했기 때문에 i == 20인지 확인합니다. for 루프가 성공적으로 실행되면 i = 20에서 멈추고 입력에 문제가 없으며 0을 반환 할 수 있습니다 (이는 메서드가 성공했음을 의미 함). sscanf는 첫 번째 = 버퍼로, last = buffer2로 만듭니다. – Snow

답변

1

프로그램의 주요 논리 오류가 동시에에서 두 배열 에 고정 된 횟수의 반복 (20)와 for 루프를 실행하고 있다는 사실이다. 성 및 이름 배열에 대해 두 개의 별도 루프를 실행해야합니다. 또한 각 배열의 strlen에 대해서만이 두 루프를 실행해야합니다. 다음 예제를 참조하십시오

for (i = 0; i < strlen(buffer); i++) 
{ 
    /* your existing stuff for the "buffer" */ 
} 

for (i = 0; i < strlen(buffer1); i++) 
{ 
    /* your existing stuff for the "buffer1" */ 
} 
+0

@WeatherVane, 귀하의 의견을 보내 주셔서 감사합니다. "@ snow"도 읽어주세요. – VHS

+0

정말 고마워요! 내 프로그램은 이제 의도 된대로 작동합니다. 두 번째 루프에서 i를 j로 변경했습니다. 두 루프 모두 성공했는지 확인해야합니다. 날씨 베인 (Weather Vane)의 회신에서 그게 무슨 뜻인지 모르겠습니다. – Snow

+0

@WeatherVane 알겠습니다. 이것은'buffer [strlen (buffer)] = '/ 0 ''라고 말하는 것만 큼 간단한가요? 아니면 훨씬 더 복잡한 것이 있습니까? – Snow

0

경고 : VHS의 주요 문제가있어. 그러나 이것은 또한 향상시킬 수있는 코드의 구조적 문제를 지적합니다. 거의 모든 코드가 각 배열에 대해 복제됩니다.

어레이에서 작동하는 기능을 만들면 문제를 더 쉽게 볼 수 있습니다. 나는이 [용서하십시오 무상 스타일 정리]를 추가하는 코드를 재 작업 한

:

#include <stdio.h> 
#include <string.h> 
#include <ctype.h> 

#define LINESIZE 80 

int 
bufdo(char *buf) 
{ 
    int len; 
    int idx; 
    int chr; 
    int ret; 

    len = strlen(buf); 

    do { 
     // assume non-conforming 
     ret = -1; 

     // length too great 
     if (len >= 20) 
      break; 

     // length too small 
     if (len < 2) 
      break; 

     // begins with hyphen 
     if (buf[0] == '-') 
      break; 

     // ends with hyphen 
     if (buf[len - 1] == '-') 
      break; 

     // assume it will be okay 
     ret = len; 

     // convert to lowercase and check for bad chars 
     for (idx = 0; idx < len; ++idx) { 
      chr = buf[idx]; 

      if (isalpha(chr)) { 
       chr = tolower(chr); 
       buf[idx] = chr; 
       continue; 
      } 

      // non-hyphen char in name 
      if (chr != '-') { 
       ret = -1; 
       break; 
      } 
     } 
    } while (0); 

    return ret; 
} 

int 
get_name(char *first, char *last) 
{ 

    char input[LINESIZE]; 
    char buffer[LINESIZE]; 
    char buffer2[LINESIZE]; 
    int len1; 
    int len2; 
    int ret; 

    ret = -1; 

    while (1) { 
     printf("\n%s", "Enter the Student Name "); 
     fflush(stdout); 

     if (!fgets(input, LINESIZE, stdin)) { 
      clearerr(stdin); 
      break; 
     } 

     if (sscanf(input, "%s %s", buffer, buffer2) != 2) 
      continue; 

     len1 = bufdo(buffer); 
     len2 = bufdo(buffer2); 

     if ((len1 > 0) && (len2 > 0)) { 
      strcpy(first,buffer); 
      strcpy(last,buffer2); 
      ret = 0; 
      break; 
     } 
    } 

    return ret; 
} 
+0

고마워요! 이것은 확실히 깔끔한 방법입니다. – Snow

+0

당신을 진심으로 환영합니다! 필자는 단편적인 기능을 구축했다. 원래는 getlen이라고하고 strlen과 length range 검사를했습니다. 나는 다른 단계들을위한 다른 기능들을 만들려고했지만, 기능들에 "잘 들어 맞았다"는 것을 깨달았을 때 다른 단계들/단계들을 하나씩 추가했다. 결국, 단일 기능으로 충분했습니다. 경험상 좋은 방법은 "척도"를 고려하는 것입니다 (즉, 내 코드 _scale_가 충분합니까?). 좀 더 많은 경험을 통해 이러한 디자인 선택은보다 쉽게 ​​알 수 있고 [거의] 공리 적입니다. 해피 프로그래밍! –