이 문제에 관한 빠른 질문, 왜 문자열에서 두 번째 값 (변환 된 두 번째 값)을 인쇄하지 않습니까?
문제
빠른 질문, 내가 여기서 잘못한 일. 이 코드의 목적은 입력을 문자열로 가져 오는 것입니다. 입력은 "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
입력 문자열에서 읽기 시작 위치를 지정하고 인덱스가 중단 된 인덱스를 반환 한 경우 인수를 가져옵니다.