Быстрый вопрос, касающийся этой проблемы: почему он не печатает второе значение (преобразованное второе значение) в строке? - PullRequest
0 голосов
/ 08 марта 2010

Быстрый вопрос, что я тут не так сделал. Целью этого кода является получение входных данных в строку, в которой вводится «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 ]

4 голосов
/ 08 марта 2010

В вашей программе есть несколько проблем:

  • Вы используете тот же индекс в expr и temp массивы. Это работает для первый раз, так как оба будут 0 для начала, но когда вы хотите обработать 2nd число, вам нужно сбросить индекс в массив temp вернуться к 0. Ясно, что это не может быть сделано с использованием одного индекса. Вы будете должны использовать два индекса, i и j.
  • К тому времени, как вы завершите обработка 2-го числа (34 в "12 34") вы достигнете конца строка и, следовательно, sscanf никогда запускается во второй раз (в Вообщем по последнему случаю). Так после цикла вам нужен другой 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

Ваш подход очень хрупкий ... если пользователь вводит несколько пробелов между входными числами ... ваша программа не сможет.

0 голосов
/ 08 марта 2010

Основная проблема заключается в том, что 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 было бы лучше принять аргумент, указывающий, с чего начать чтение из входной строки и вернул ли он индекс, где он остановился.

...