2017-01-27 2 views
3
#include <stdio.h> 

int main() { 
    int i; 
    char arr[100]; 

    for (i = 0; i < 100; i++) 
     scanf("%c", &arr[i]); 
    for (i = 0; i < 100; i++) { 
     if ('a' <= arr[i] && arr[i] <= 'z') 
      arr[i] =-32; 
     else 
     if ('A' <= arr[i] && arr[i] <= 'Z') 
      arr[i] =+32; 
    } 
    printf("%s", arr); 
    return 0; 
} 

Там была проблема:Switching случая каждой буквы в строке

Вы получили строку, состоящую из заглавных и строчных латинских алфавитов. Вам нужно изменить случай каждого алфавита в этой строке. То есть все заглавные буквы должны быть преобразованы в нижний регистр, и все строчные буквы должны быть преобразованы в верхний регистр. Затем вам нужно напечатать итоговую строку для вывода.

Что не так с вышеуказанным кодом? Он успешно компилируется, но есть ошибка времени выполнения.

+1

А что такое ошибка времени выполнения? Какую строку вы вводите? –

+0

Проблема * очевидна * заключается в том, что вы не завершаете строку. –

+1

Включите предупреждения в своем компиляторе. Я уверен, что это даст вам предупреждения, по крайней мере. –

ответ

4

Есть несколько проблем в коде:

  • основной проблемой является далеко вы регулируете случай: arr[i] =-32; не уменьшаем arr[i] по 32, но сохраняет 32 в arr[i]. Комбинированный оператор присваивания указан -=. У вас такая же проблема для += в другом случае.

  • Преобразование строчной буквы в верхний регистр путем вычитания 32 работает для ASCII, но не переносится на другие наборы символов. Аналогично, по сравнению с 'a' и 'z' работает для ASCII, но не для EBCDIC. Вы должны использовать функции от <ctype.h>.

  • вы читаете 100 символов с scanf("%c"...), но вы не проверяете возвращаемое значение, и вы не завершаете нулевой массив. Кроме того, вы должны прочитать не более одного размера, чем размер массива, чтобы оставить пробел для байта '\0'. Как закодировано, ваша программа вызывает неопределенное поведение в printf("%s", arr);, потому что arr не имеет значения null.

Вот исправленный вариант:

#include <ctype.h> 
#include <stdio.h> 

int main(void) { 
    int c; 

    while ((c = getchar()) != EOF) { 
     if (isupper(c)) 
      c = tolower(c); 
     else 
     if (islower(c)) 
      c = toupper(c); 

     putchar(c); 
    } 
    return 0; 
} 
+0

+1 Хорошо, мне очень нравится этот ответ. Могу ли я отменить предыдущий ответ и выбрать ваш как лучший? Кроме того, почему мы объявляем c как int, когда будем брать символы? –

+0

@KaranSingh: 'c' определяется как' int' для обработки всех значений, возвращаемых 'getc()': все значения 'unsigned char' плюс специальное значение' EOF'. Тип 'char' не может корректно обрабатывать все случаи. 'EOF' будет либо совпадать с' '\ 377'' (' 'ÿ'' в iso-latin1), либо никогда не будет соответствовать. – chqrlie

2

Наиболее очевидной проблемой является то, что вы не завершаете нуль строку, поэтому при вызове printf("%s", arr) поведение будет непредсказуемым.

1

Для того, чтобы printf("%s", arr), вам необходимо завершить arr с нулевым символом.

Один из способов сделать это является:

  • Объявление char arr[101]
  • Установка arr[100] = 0
2

Проблема с кодом является то, что он никогда не заканчивает строку. Если вы прочтете 100 символов, а затем вы хотите распечатать их с %s в printf, вы должны добавить нулевой терминатор в конце, как это:

char arr[100+1]; // See +1 
... // Reading code 
arr[100] = '\0'; 

Обратите внимание, что функции библиотеки islower/isupper обеспечивают портативные, и гораздо более читаемый подход к тестированию типа символа. Аналогичным образом, tolower/toupper предоставляют дополнительную информацию о ваших намерениях читателю вашего кода, чем просто добавление и вычитание 32. Кроме того, код C, который использует эти стандартные функции, будет работать с системами с кодировкой символов, отличной от ASCII.

+0

что, если моя строка не 100 букв долго, и я все еще хочу его прекратить. Как мне это сделать? и есть несколько комментариев, которые я сделал по этому вопросу. –

+0

@KaranSingh Если вы хотите завершить строку в позиции 'n', используйте' arr [n] = '\ 0'; 'Написание нуля в одной позиции после последнего символа - это все, что вам нужно сделать. – dasblinkenlight

0

Ваш код имеет Serveral вопросы: не-нуль-терминатором строки ввода, ненадлежащее нижний/верхний регистр преобразования и путаницы с = -/- = и = +/+ = операторы.

Следующий код основан на вашем:

В качестве альтернативы, чтобы получить строку с завершающим нулем он использует fgets() вместо зсап(), только для примера.

Также использует функции библиотеки C для избежания проблем с разными кодировками, упрощая условия и для операций с верхним/нижним регистром.

Отредактировано для улучшения качества кода, как указано в комментарии @chqrlie.

#include <stdio.h> 
#include <ctype.h> 

int main() 
{ 
    int i; 
    char arr[101]; 

    printf("Enter string: "); 
    fgets(arr, sizeof(arr), stdin);; 
    for(i=0;i<strlen(arr); i++) 
    { 
     int value = (unsigned char) arr[i]; // to properly use int parameters, as expected by ctype.h next functions 
     if (isupper(value)) 
     { 
      arr[i]=tolower(value); 
     } 
     else { 
      if (islower(value)) 
      { 
       arr[i]=toupper(value); 
      } 
     } 
    } 
    printf("%s", arr); 

    return 0; 
} 

Попробуй here.

+0

-1 для использования небезопасной, устаревшей функции 'gets()'. Кроме того, вы используете 'tolower' и' toupper', вы также должны использовать 'islower()' и 'isupper()' и использовать аргумент 'char' как' (unsigned char) '. Отказ от ответственности - хромое оправдание, используйте 'fgets()'. – chqrlie

+0

@chqrlie, ты прав. Как уже упоминалось ранее, я использовал get(), чтобы упростить пример. Но я согласен с вами в отношении (плохого) использования устаревших функций. Отредактировано для использования действующей в настоящее время альтернативы. – MarcM

+0

Я снял нижний план. Обратите внимание также на проблему с подписанными аргументами char для 'islower()', 'isupper()' и т. Д. – chqrlie

Смежные вопросы