Новое в C: что не так с моей программой? - PullRequest
2 голосов
/ 01 декабря 2010

Я довольно хорошо разбираюсь в рубине и учу себя Си, начиная с нескольких игрушечных программ.Это просто для вычисления среднего числа строк, которые я ввожу в качестве аргумента.

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

main(int argc, char *argv[])
{
   char *token;
   int sum = 0;
   int count = 0;
   token = strtok(argv[1],",");
   while (token != NULL)
   {
     count++;
     sum += (int)*token;
     token = strtok(NULL, ",");
   }

 printf("Avg: %d", sum/count);
 printf("\n");
 return 0;
}

Вывод:

mike@sleepycat:~/projects/cee$ ./avg 1,1
Avg: 49

Что явно требует некоторой корректировки.

Буду признателен за любые улучшения и объяснения.

Ответы [ 8 ]

5 голосов
/ 01 декабря 2010

Ищите sscanf или atoi как функции для преобразования из строки (массива символов) в целое число.

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

3 голосов
/ 01 декабря 2010

strtok (

Пожалуйста, пожалуйста, не используйте это. Даже его собственная документация говорит, что никогда не использовать его. Я не знаю, как вы, как программист на Ruby, узнали о его существовании, но, пожалуйста, забудьте об этом.

(int)*token

Это даже не близко к тому, что ты хочешь. Есть две фундаментальные проблемы:

1) Символ * не «содержит» текст. Это указывает на текст. token относится к типу char*; следовательно, *token имеет тип char. То есть один байт, а не строка. Обратите внимание, что я сказал «байт», а не «символ», потому что имя char на самом деле неверно - понятный недосмотр со стороны разработчиков языка, потому что Unicode тогда еще не существовал. Пожалуйста, поймите, что char в основном является числовым типом. Существует нет реального типа текста в C! Интерпретация последовательности char значений в виде текста просто соглашение .

2) При сотворении в C магические преобразования не выполняются.

Ваш код выполняет захват байта, на который указывает token (после вызова strtok()), и преобразует это числовое значение в int. Байт, который отображается с символом 1, на самом деле имеет значение 49. Снова, интерпретация последовательности байтов как текста - это просто соглашение, и, таким образом, интерпретация байта как символа - просто соглашение - в частности, здесь мы используя соглашение, известное как ASCII. Когда вы нажимаете клавишу 1 на клавиатуре, а затем нажимаете Enter, чтобы запустить программу, цепочка событий, запускаемых командным окном, фактически передает байт со значением 49 в вашу программу. (Точно так же запятая имеет значение 44).


Обе вышеперечисленные проблемы решаются с помощью соответствующих инструментов для разбора ввода. Посмотрите вверх sscanf(). Тем не менее, вы даже не хотите передавать ввод в вашу программу таким образом , потому что вы не можете поставить пробелы во входных данных - каждое «слово» в командной строке будет передаваться как отдельный запись в массиве argv [].

На самом деле вы должны воспользоваться этим , просто ожидая, что каждая запись в argv [] будет представлять одно число. Вы можете снова использовать sscanf() для разбора каждой записи, и это будет намного проще.


И наконец:

printf («Ср .:% d», сумма / количество)

Коэффициент sum/count не даст вам десятичного результата. Деление целого числа на другое целое дает целое число в C, отбрасывая остаток.

3 голосов
/ 01 декабря 2010

В C, если вы преобразуете char в int, вы просто получаете значение ASCII . Таким образом, вы усредняете значение ascii символа 1 дважды и получаете то, что ожидаете.

Вы, вероятно, хотите использовать atoi().

РЕДАКТИРОВАТЬ: Обратите внимание, что это, как правило, верно для всех типов типов в C. C не интерпретирует значения для вас, он доверяет вам знать, что существует в данном месте.

3 голосов
/ 01 декабря 2010

Проблема в том, что символ "1" равен 49. Вы должны преобразовать значение символа в целое число, а затем в среднее значение.

3 голосов
/ 01 декабря 2010

49 - значение ASCII символа '1'.

Это должно быть полезно для вас ....: D

2 голосов
/ 01 декабря 2010

В этой строке: sum += (int)*token; Приведение char к int принимает значение ASCII char . для 1 это значение равно 49.

Вместо этого используйте функцию atoi :

sum += atoi(token);

Примечание atoi находится в файле stdlib.h, поэтому вам необходимо # включить также.

2 голосов
/ 01 декабря 2010

Вы не можете преобразовать строку в целое число через

sum += (int)*token;

Вместо этого вы должны вызвать такую ​​функцию, как atoi():

sum += atoi (token);
1 голос
/ 01 декабря 2010

когда вы приводите char (то есть, что является * токеном) к int, вы получаете его значение ascii в C - которое составляет 49 ... так что среднее значение chars ascii на самом деле составляет 49. вам нужно использовать atoi чтобы получить значение числа, представленного

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...