关于这个问题的快速问题,为什么不打印字符串上的第二个值(转换后的第二个值)?

时间:2010-03-08 09:14:28

标签: c string integer scanf

快速提问,我在这里做错了什么。此代码的目的是将输入转换为字符串,输入为“12 34”,在“12”和“32”之间有一个空格,并从一个整数变量转换并打印两个单独的数字数。为什么第二次调用函数copyTemp不会产生值34?我有一个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'; 
}

2 个答案:

答案 0 :(得分:4)

您的计划中存在一些问题:

  • 您正在使用相同的索引 exprtemp数组。这适用于 这两次都是第一次0 开始但是当你想要 处理2nd号码,您需要 将索引重置为temp数组 回到0。显然这不可能 使用单个索引完成。你会 必须使用两个索引,ij
  • 当你完成时 处理第二个数字(34 in "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

你的方法非常脆弱......如果用户在输入数字之间给出多个空格......你的程序就会失败。

答案 1 :(得分:0)

主要问题是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最好采用一个参数来指定从输入字符串开始读取的位置,以及它是否从它停止的位置返回索引。