как исправить этот код, чтобы он мог проверить целые числа, присутствующие рядом с символом? - PullRequest
1 голос
/ 23 мая 2019

Учитывая строку, содержащую буквенно-цифровые символы, вычислите сумму всех чисел, присутствующих в строке. Проблема моего кода в том, что он отображает целые числа, присутствующие перед символами, но не суммирует целые числа после символов.

Выполнение легко в Python и C ++, но я не могу сделать это, используя C! Может кто-нибудь проверить, где я сделал не так? << спасибо! </p>

enter code here
#include<stdio.h>
#include<string.h>
int convert(char[]);
int main()
{
    char ch[100],temp[100]={0};
    int i=0,s=0,j=0,n;
    scanf("%s",ch);
    for(i=0;i<strlen(ch);i++)
    {  
        if((ch[i]>='0') && (ch[i]<='9'))
        {
            temp[j]=ch[i]; 
            j++;
        }
        else
        {   
            if(temp[0]== '\0')
            {
                continue;
            }
            else 
            {
                n=convert(temp);
                s+=n;
                temp[0]= '\0';
                j=0;
            }
        }
    }
    printf("%d",s);
    return 0;
}
int convert(char s[]) //converting string to integer
{
    int n=0;
    for(int i=0;i<strlen(s);i++)
    {
        n= n * 10 + s[i] - '0'; 
    }
return n;
}

Ввод: 12abcd4
Ожидаемый выход: 16

Но вывод для моего кода - 12.

Ответы [ 2 ]

1 голос
/ 23 мая 2019

Для этого можно использовать комбинацию strtoul() и strpbrk().

Объявить двухсимвольные указатели start_ptr и end_ptr иstart_ptr указывает на начало рассматриваемой строки.

char *start_ptr=s, *end_ptr;

, где s - это массив символов размером 100, содержащий строку.

Поскольку ваша строка содержит только буквенно-цифровые символы, знак - отсутствует и, следовательно, нетотрицательные числа.Таким образом, мы можем избежать использования целых чисел без знака.

Мы используем strtoul() из stdlib.h для выполнения преобразования строки в целое число.Итак, давайте объявим две переменные: rv для хранения значения, возвращенного strtoul() и sum для хранения суммы чисел.

unsigned long rv, sum_val=0;

Теперь используем цикл:

for(; start_ptr!=NULL; )
{
    rv = strtoul(start_ptr, &end_ptr, 10);
    if(rv==ULONG_MAX && errno==ERANGE)
    {
        //out of range!
        printf("\nOut of range.");
        break;
    }
    else
    {
        printf("\n%lu", rv);
        sum_val += rv;
        start_ptr=strpbrk(end_ptr, "0123456789");
    }
}

strtoul() преобразует максимально возможную часть строки, а затем заставляет end_ptr указывать на первый символ части строки, которая не может быть преобразована.

Возвращает ULONG_MAXесли число слишком велико и errno будет установлено на ERANGE.

В противном случае возвращается преобразованное число.

strpbrk() будет искатьнабор символов (в данном случае символы 0-9) и возврат указателя на первое совпадение.В противном случае возвращается NULL.

Не забудьте включить следующие заголовочные файлы:

stdlib.h ---> strtoul
string.h ---> strpbrk
limits.h ---> ULONG_MAX
errno.h  ---> errno

Короче говоря, мы могли бы сделать программу примерно такой, как

for(; start_ptr!=NULL; sum_val += rv, start_ptr=strpbrk(end_ptr, "0123456789"))
{
    rv = strtoul(start_ptr, &end_ptr, 10);
    if(rv==ULONG_MAX && errno==ERANGE)
    {
        //out of range!
        break;
    }
}
printf("\n\n%lu", sum_val);

Таким образом, значение sum_val для строки "12abcd4" будет равно 16.


scanf(), как правило, не лучший способ принять ввод, который не имеет надлежащего формата.Возможно, вместо этого вы можете использовать fgets() - sscanf() combo.

Если вы должны использовать scanf(), убедитесь, что вы проверили возвращаемое им значение, которое в вашем случае должно быть 1 (число успешных назначений, выполненных scanf()).

И для предотвращения переполнения используйте спецификатор ширины, как в

scanf("%99s",ch);

вместо

scanf("%s",ch);

как 100 - это размер массива символов ch, и нам нужен один дополнительный байт для хранения разделителя строк (символ \0).

0 голосов
/ 23 мая 2019

В вашем коде есть две проблемы. Первое было упомянуто в комментариях: если последний символ является цифрой, последний «номер раздела» не будет учитываться. Но я не думаю, что решение, данное в комментариях, является хорошим, потому что, если последний символ не является цифрой, у вас будет неправильное значение. Чтобы исправить это, я добавил оператор if, который проверяет, является ли последний символ цифрой, если это так, вызовите convert ().

Вторая проблема заключается в том, что strlen возвращает количество символов в вашей строке от начала до тех пор, пока не найдет '\ 0'. То, как вы использовали вашу строку, привело к следующей проблеме:
ch = "12abcd4".
Сначала у вас есть temp = '1' + '2' + '\ 0' ...
После вызова convert () вы устанавливаете temp [0] в '\ 0', таким образом, temp = '\ 0' + '2' + '\ 0' ....
И когда вы начинаете читать цифру снова, вы устанавливаете «4» в temp [0]. Ваша строка теперь: '4' + '2' + '\ 0' ....
Возвращенное n будет 42, а ваш результат 54 (12 + 42). Есть несколько решений, чтобы иметь ожидаемое поведение, я решил использовать вашу переменную j, чтобы указать, сколько символов следует прочитать вместо использования strlen ():

#include<stdio.h>
#include<string.h>

int convert(char[], int size);

int main() {
  char ch[100],temp[100]={0};
  int i=0,s=0,j=0,n;
  scanf("%s",ch);
  for(i=0;i<strlen(ch);i++) {
    if((ch[i]>='0') && (ch[i]<='9')) {
      temp[j]=ch[i]; 
      j++;

      // change here
      if(i == strlen(ch) - 1) {
        n=convert(temp, j);
        s+=n;
      }
    }
    else {
      // change here
      n=convert(temp, j);
      s+=n;

      if(temp[0]== '\0') {
    continue;
      }

      temp[0]= '\0';
      j=0;
    }
  }
  printf("%d\n",s);
  return 0;
}

//change here
int convert(char s[], int size) {
  int n=0;
  for(int i=0;i<size;i++) {
    n= n * 10 + s[i] - '0';
  }
  return n;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...