쉼표로 구분 된 숫자 문자열 읽기

어묵

쉼표로 구분 된 숫자 문자열을 읽는 함수를 작성 중입니다. 문자열의 형식은 다음과 같습니다.

"1, 2, 3"

유일한 "규칙"은 함수가 각 숫자 사이에 쉼표 하나만 있는 한 공백이나 탭을 허용한다는 것 입니다.

문자열이 유효하면 번호가 연결 목록에 저장됩니다.

예를 들어 다음 문자열이 유효합니다 .

"1,2,14,2,80"
"  250  ,  1,  88"

그러나 다음은 유효하지 않습니다 .

" 5, 1, 3 ,"
"51, 60, 5,,9"

처음에는 strtok () (구분 기호 ", \ t"를 사용하여 운을 시도했지만 지금은 이해 한 바에 따르면 오류를 확인하는 것이 불가능합니다. 그래서 제 자신의 함수를 작성했지만 매우 만족스럽지 않습니다.- 나는 코드가 꽤 나쁘다고 생각하고 작동하는 것처럼 보이지만 그러한 기능을 구현하는 더 깨끗하고 쉬운 방법이 있는지 정말로 알고 싶습니다.

내 기능은 다음과 같습니다.

void sliceNumbers(char * string)
{
  /*flag which marks if we're expecting a comma or not*/
  int comma = FALSE;
  /*Are we inside a number?*/
  int nFlag = TRUE;
  /*error flag*/
  int error = FALSE;
  /*pointer to string start*/
  char * pStart = string;
  /*pointer to string end*/
  char * pEnd = pStart;

  /*if received string is null*/
  if (!string)
  {
    /*add error and exit function*/
    printf("You must specify numbers");
    return;
  }
  /*this loop checks if all characters in the string are legal*/
  while (*pStart != '\0')
  {
    if ((isdigit(*pStart)) || (*pStart == ',') || (*pStart == ' ') || (*pStart == '\t'))
    {
      pStart++;
    }
    else
    {
      char tmp[2];
      tmp[0] = *pStart;
      tmp[1] = 0;
      printf("Invalid character");
      error = TRUE;
      pStart++;
    }
  }
  if (!error)
  {
    pStart = string;
    if (*pStart == ',')
    {
    printf("Cannot start data list with a comma");
    return;
    }
    pEnd = pStart;
    while (*pEnd != '\0')
    {
      if (comma)
      {
        if (*pEnd == ',')
        {
          if (!nFlag)
          {

          }
          if (*(pEnd + 1) == '\0')
          {
            printf("Too many commas");
            return;
          }
          *pEnd = '\0';
          /*Add the number to the linked list*/
          addNumber(pStart, line, DC);
          comma = FALSE;
          nFlag = FALSE;
          pStart = pEnd;
          pStart++;
          pEnd = pStart;
        }
        else if (isdigit(*pEnd))
        {
          if (!nFlag)
          {
            printf("numbers must be seperated by commas");
            pEnd++;
          }
          else
          {
            if (*(pEnd + 1) == '\0')
            {
              pEnd++;
              /*Add the number to the linked list*/
              addNumber(pStart);
              comma = FALSE;
              nFlag = FALSE;
              pStart = pEnd;
              pStart++;
              pEnd = pStart;
            }
            else
            {
              pEnd++;
            }
          }
        }
        else if (*pEnd == '\0')
        {
          if (nFlag)
          {
            /*Add the number to the linked list*/
            addNumber(pStart, line, DC);
          }
          else
          {
            printf("Too many commas");
          }

        }
        else if (*pEnd == ' ' || *pEnd == '\t')
        {
          nFlag = FALSE;
          pEnd++;
        }
      }
      else
      {
        if (*pEnd == ',')
        {
          printf("There must be only 1 comma between numbers");
          return;

        }
        else if (isdigit(*pEnd))
        {
          if (*(pEnd + 1) == '\0')
          {
            pEnd++;
            /*Add the number to the linked list*/
            addnumber(pStart, line, DC);
            comma = FALSE;
            nFlag = FALSE;
            pStart = pEnd;
            pStart++;
            pEnd = pStart;
          }
          else
          {
            pStart = pEnd;
            pEnd++;
            nFlag = TRUE;
            comma = TRUE;
          }
        }
        else if (*pEnd == ' ' || *pEnd == '\t')
        {
          if (!nFlag)
          {
            pEnd++;
          }
          else
          {
            pEnd++;
          }
        }
      }
    }
  }
}
날씬한

int현재 상태를 추적 하는 여러 부울 ( s 로 선언 했더라도)을 정의했습니다 . 가능한 값을 정의하는 데 state사용하여 #define이를 하나의 변수 로 결합 할 수 있습니다.

#define STATE_START 0
#define STATE_IN_NUMBER 1
#define STATE_COMMA 2
#define STATE_FINISHED 3
#define STATE_ERROR 4

int state = STATE_START;

각 캐릭터가 한 상태에서 다른 상태로 이동하는 방법을 보여주는 다이어그램 (흐름도와 비슷 함)을 그릴 수 있습니다.

여기에 이미지 설명 입력

(내 이미지의 경우 단순하게 유지하고 공백없이 입력에 대해 오류가없는 상태 만 표시했습니다.)

또는 그냥 말로 표현하세요 :

current state   | input     | next state| side effect
-----------------------------------------------------------------------
START           | digit     | IN_NUMBER | start storing a number
START           | other     | ERROR     | 
IN_NUMBER       | digit     | IN_NUMBER | continue storing a number
IN_NUMBER       | comma     | COMMA     | complete storing a number
IN_NUMBER       | null      | FINISHED  | finalise output
IN_NUMBER       | other     | ERROR     | report error
COMMA           | digit     | IN_NUMBER | start storing a number
COMMA           | comma     | ERROR     |
COMMA           | other     | ERROR     |

(내 테이블의 경우 기본 오류 상태를 추가했지만 여전히 공백을 고려하지 않았습니다)

공백과 탭을 처리하려면 상태와 전환을 더 추가해야하지만 원칙은 변경되지 않습니다. 공백없이 작동하는 구현으로 시작한 다음 추가하는 것이 좋습니다.

이를 통해 유한 상태 머신 을 작성할 수 있으며 , 구현 중 하나는 다음과 같습니다.

int state = STATE_START;
while(state != STATE_FINISHED && state != STATE_ERROR) {
    char c = input[offset++];
    switch(state) {
        case STATE_START:
            state = handleStateStart(...);
            break;
        case STATE_IN_NUMBER:
            state = handleInNumber(...);
            break;
        // etc.
        default:
            sprintf(error_message, "Reached unsupported state: %c", state);
            state = STATE_ERROR;
    }
}

처리 함수에 대한 매개 변수는 읽고 수정할 데이터 구조를 전달해야합니다. 예를 들면 :

int handleStateStart(
    char c,
    int* current_number,
    char *error_message) 
{
    if( ! isDigit(c)) {
        sprintf(error_message, "Expected a digit at char %d", *offset);
        return STATE_ERROR;
    }
    *current_number = atoi(c);
    return STATE_IN_NUMBER;
}

(이것은 상태 머신을 구현하는 이해하기 쉬운 방법이지만이를 수행하는 다른 방법 이 있습니다. 일반적인 상태 머신 구현 패턴이 있습니까? )

CSV 구문 분석 문제는 상태 시스템에 매우 적합하며 결과 코드는 매우 깔끔하고 깔끔합니다. 상태 머신은 더 복잡한 구문 분석 작업에 사용되며 컴파일러와 같은 작업에 많이 사용됩니다. 나중에 연구에서 정규식을 접하게됩니다. 공식적으로 정규식은 문자를 소비하는 유한 상태 기계를 표현하는 간결한 방법입니다.

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

MySQL-쉼표로 구분 된 숫자 문자열에서 숫자 찾기

쉼표로 구분 된 문자열 읽기

쉼표로 구분 된 문자열에서 첫 번째 숫자 가져 오기

txt 파일 내에 쉼표로 구분 된 숫자 문자열 만들기

문자열 기반 SQL 검색 쿼리-쉼표로 구분 된 숫자

DataFrame에서 Python의 문자열로 쉼표로 구분 된 시퀀스 읽기

숫자를 쉼표로 구분 된 문자열로 반환

read.csv ()를 사용하여 쉼표로 구분 된 문자열 읽기

쉼표로 구분 된 문자열에서 Web.config 설정 읽기

파이썬의 문자열 객체에서 쉼표로 구분 된 값 읽기

쉼표로 구분 된 숫자 문자열 정렬

MySQL 쉼표로 구분 된 문자열

쉼표로 구분 된 문자열

쉼표로 구분된 문자열에서 목록 만들기

쉼표로 구분 된 문자열 mysql에서 값 찾기

쉼표로 구분 된 목록에서 문자열 값 찾기

쉼표로 구분 된 VB.Net 문자열 바꾸기

쉼표로 구분 된 SQlite 큰 숫자

쉼표로 구분 된 숫자 문자열을 숫자로 변환

쉼표로 구분 된 영숫자 텍스트에서 문자열을 추출하기위한 정규식

파이썬에서 쉼표로 구분 된 문자열의 모든 숫자 찾기

쉼표로 구분 된 숫자 문자열을 2D 배열로 변환

쉼표로 구분 된 작은 따옴표로 묶인 문자열 바꾸기

선행 문자를 기반으로 쉼표로 구분 된 문자열을 벡터로 구문 분석

파이썬에서 쉼표로 구분된 문자열 자르기

쉼표와 문자로 구분 된 문자열의 값 분할

C에서 쉼표로 구분된 문자열 구문 분석

Java: 쉼표로 구분된 숫자를 숫자로 숨김

쉼표로 구분 된 문자열에서 변형 배열 채우기

TOP 리스트

  1. 1

    JNDI를 사용하여 Spring Boot에서 다중 데이터 소스 구성

  2. 2

    std :: regex의 일관성없는 동작

  3. 3

    JSoup javax.net.ssl.SSLHandshakeException : <url>과 일치하는 주체 대체 DNS 이름이 없습니다.

  4. 4

    PrematureCloseException : 연결이 너무 일찍 닫혔습니다.

  5. 5

    Xcode10 유효성 검사 : 이미지에 투명성이 없지만 여전히 수락되지 않습니까?

  6. 6

    정점 셰이더에서 카메라에서 개체까지의 XY 거리

  7. 7

    Ionic 2 로더가 적시에 표시되지 않음

  8. 8

    Seaborn에서 축 제목 숨기기

  9. 9

    C #에서 'System.DBNull'형식의 개체를 'System.String'형식으로 캐스팅 할 수 없습니다.

  10. 10

    복사 / 붙여 넣기 비활성화

  11. 11

    ArrayBufferLike의 typescript 정의의 깊은 의미

  12. 12

    Google Play Console에서 '예기치 않은 오류가 발생했습니다. 나중에 다시 시도해주세요. (7100000)'오류를 수정하는 방법은 무엇입니까?

  13. 13

    Kubernetes Horizontal Pod Autoscaler (HPA) 테스트

  14. 14

    jfreecharts에서 x 및 y 축 선을 조정하는 방법

  15. 15

    PRNG 기간보다 순열이 더 많은 목록을 무작위로 섞는 방법은 무엇입니까?

  16. 16

    C # HttpWebRequest 기본 연결이 닫혔습니다. 전송시 예기치 않은 오류가 발생했습니다.

  17. 17

    다음 컨트롤이 추가되었지만 사용할 수 없습니다.

  18. 18

    잘못된 구성 개체입니다. Webpack이 Angular의 API 스키마와 일치하지 않는 구성 개체를 사용하여 초기화되었습니다.

  19. 19

    Android Kotlin은 다른 활동에서 함수를 호출합니다.

  20. 20

    R의 마침표와 숫자 사이에 문자열 삽입

  21. 21

    Assets의 BitmapFactory.decodeStream이 Android 7에서 null을 반환합니다.

뜨겁다태그

보관