이 문제에 관한 빠른 질문, 왜 문자열에서 두 번째 값 (변환 된 두 번째 값)을 인쇄하지 않습니까?

StackOverflow https://stackoverflow.com/questions/2400254

  •  18-09-2019
  •  | 
  •  

문제

빠른 질문, 내가 여기서 잘못한 일. 이 코드의 목적은 입력을 문자열로 가져 오는 것입니다. 입력은 "12"와 "32"사이에 공간이있는 "12 34"입니다. 숫자. 기능 CopyTemp에 대한 두 번째 호출이없는 이유는 무엇입니까? 문자열 인덱스를 추적하는 index_counter 변수가 있으며 '공간'문자를 건너 뛰는 것을 의미합니다. 내가 무엇을 잘못 했습니까?

감사해요.

#include <stdio.h>
#include <string.h>
int index_counter = 0;
int number;
void copyTemp(char *expr,char *temp);

int main(){
 char exprstn[80]; //as global?
 char tempstr[80];

 gets(exprstn);
 copyTemp(exprstn,tempstr);
 printf("Expression: %s\n",exprstn);
 printf("Temporary: %s\n",tempstr);
 printf("number is: %d\n",number);
 copyTemp(exprstn,tempstr);      //second call produces same output shouldnt it now produce 34 in the variable number?
 printf("Expression: %s\n",exprstn);
 printf("Temporary: %s\n",tempstr);
 printf("number is: %d\n",number);

 return 0;
}
void copyTemp(char *expr,char *temp){
 int i;
 for(i = index_counter; expr[i] != '\0'; i++){
  if (expr[i] == '0'){
   temp[i] = expr[i];
  }
  if (expr[i] == '1'){
   temp[i] = expr[i];
  }
  if (expr[i] == '2'){
   temp[i] = expr[i];
  }
  if (expr[i] == '3'){
   temp[i] = expr[i];
  }
  if (expr[i] == '4'){
   temp[i] = expr[i];
  }
  if (expr[i] == '5'){
   temp[i] = expr[i];
  }
  if (expr[i] == '6'){
   temp[i] = expr[i];
  }
  if (expr[i] == '7'){
   temp[i] = expr[i];
  }
  if (expr[i] == '8'){
   temp[i] = expr[i];
  }
  if (expr[i] == '9'){
   temp[i] = expr[i];
  }
  if (expr[i] == ' '){ 
   temp[i] = '\0';
   sscanf(temp,"%d",&number); 
   index_counter = i+1; //skips?
  }
 }
 // is this included here? temp[i] = '\0'; 
}
도움이 되었습니까?

해결책

프로그램에는 몇 가지 문제가 있습니다.

  • 동일한 인덱스를 사용하고 있습니다expr 그리고 temp 배열. 이것은 둘 다 0시작하지만 처리하고 싶을 때 2nd 숫자, 인덱스를 temp 배열로 돌아갑니다 0. 분명히 이것은 단일 색인을 사용하여 수행 할 수 없습니다. 두 개의 지수를 사용해야합니다. i 그리고 j.
  • 두 번째 숫자의 처리를 완료 할 때까지 ( 34 안에"12 34") 당신은 문자열의 끝에 도달하므로 sscanf 두 번째 행사에는 결코 달리지 않습니다 (일반적으로 마지막 경우). 따라서 for 루프 후 마지막 숫자를 추출하려면 다른 SSCANF가 필요합니다. 또한 문자열에서 숫자를 추출하고 증가 한 후에는 함수에서 돌아와야합니다 i.
  • 사용하지 않아야합니다 gets() 및 사용fgets() 보안상의 이유로 인해 ().
  • 그림과 같이 숫자의 다중 테스트를 단일 테스트로 결합 할 수 있습니다.

이 같은.

void copyTemp(char *expr,char *temp){
    int i;
    int j = 0;
    for(i = index_counter; expr[i] != '\0'; i++){

        if (expr[i] >= '0' && expr[i]<='9'){
            temp[j++] = expr[i]; // copy the digit into temp..increment j.
        }    
        else if (expr[i] == ' '){ // space found..time to extract number.
            temp[j] = '\0'; // terminate the temp.
            sscanf(temp,"%d",&number); // extract.
            index_counter = i+1; // skip the space.
                    return; // done converting...return..must not continue.
        }
    }
    // have reached the end of the input string..and still need to extract a 
    // the last number from temp string.
    temp[j] = '\0';
    sscanf(temp,"%d",&number);
}

이러한 변경 후에는 예상대로 작동합니다.

$ gcc b.c 2> /dev/null && ./a.out
12 34
Expression: 12 34
Temporary: 12
number is: 12
Expression: 12 34
Temporary: 34
number is: 34

귀하의 접근 방식은 매우 취약합니다 ... 사용자가 입력 번호 사이에 여러 공간을 제공하는 경우.

다른 팁

주요 문제는 그 것입니다 copyTemp 글을 씁니다 temp[i], 그러나 각 호출 copyTemp 초기화 i 에게 index_counter, 0이 아닙니다. 이것은 각 호출을 의미합니다. copyTemp 기존에 추가됩니다 temp 이전 내용을 덮어 쓰는 대신 버퍼 sscanf 따라서 항상 같은 문자열을 다시 읽습니다. 입력 버퍼에서 읽을 위치와 출력 버퍼에 쓸 위치를 추적하려면 별도의 인덱스를 사용해야합니다.

추가 문제 :* 절대 사용하지 마십시오 ggets. 항상. 사용 fgets 대신에. * 많은 코드를 복제합니다 copyTemp. 대신 할 수 있습니다 :

if (expr[i] == '0' || expr[i] == '1' || ...)

또는 더 나은 :

if (isdigit(expr[i]))
  • copyTemp 대상 버퍼를 넘치지 않으려면 몇 가지 예방 조치를 취해야합니다. (그 점에 유의하십시오 copyTemp 대상 버퍼를 인수로 가져갈 필요조차 없습니다.)

  • 글로벌 변수를 사용하지 않아야합니다. 더 좋을 것입니다 copyTemp 입력 문자열에서 읽기 시작 위치를 지정하고 인덱스가 중단 된 인덱스를 반환 한 경우 인수를 가져옵니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top