Solaris Compiler делает мой код на C странным - PullRequest
1 голос
/ 05 апреля 2011

Я пытаюсь выполнить задание для колледжа по предмету программирования C.

Я выполнил свое задание на своем MacBook, и мой код работает отлично, как и предполагалось.Однако наш преподаватель сказал нам, что весь наш код будет скомпилирован с использованием сервера Solaris 10 для колледжа, и нам сказали, что если ваш код не будет компилироваться и выполняться на нем, оценки будут вычитаться.

Нам также сообщили, что наше приложение будет скомпилировано маркерами со следующим синтаксисом:

gcc -ansi -Wall -pedantic assign1.c -lm -o assign1

и выполнено с использованием:

./assign1

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

На моем Mac он выводит:

Enter a string (1-40 characters): asdfghjkl
Output: adfghjkls

На коробке Solaris колледжа выводит:

Enter a string (1-40 characters): asdfghjkl
Output: aa#?dfghjkls

Моя функция, которая выполняет (большую часть) вывод:

void sortLine(int *optionStats, char* source)
{
   char tempsort[MAX_SORT_LENGTH + 1];
   char comp_c;
   int i,j,k;
   char c = source[i++]; 
   i = j = k = 0;
   optionStats[2]++;
   while (c != '\n' && c != '\0' && c != EOF) {
      /* convert uppercase characters to lowercase */
      if ((int)c >= (int)'A' && (int)c <= (int)'Z') 
         c = c + ((int)'a' - (int)'A');
      /* if the character is alphabeic then sort it else skip it */
      if ((int)c <= (int)'z' && (int)c >= (int)'a') {
         for (j = 0; j <= MAX_SORT_LENGTH + 1; j++) {
            comp_c = tempsort[j];
            if (comp_c == '\n' || comp_c == '\0' || comp_c == EOF) {
               tempsort[j] = c;
               break;
            }
            if ((int)c <= (int)comp_c) {
               for (k = MAX_SORT_LENGTH + 1; k > j; k--) {
                  tempsort[k] = tempsort[k - 1];
               }
               tempsort[j] = c;
               break;
            }
         }
      }
      c = source[i++];
   }
   /* copy the sorted temporary array into the source array */
   for (i = 0; i <= MAX_SORT_LENGTH + 1; i++) {
      source[i] = tempsort[i];
   }
}

Однако пара замечаний:

  • Само определение функции (подпись) предоставляется лектором, поэтому имена, типы возвращаемых данных, параметры и т. Д. Изменить нельзя,и мы должны использовать его как есть (однако мы можем делать все, что захотим внутри него).

  • Код должен соответствовать ANSI / C90 (grr!)

Может ли кто-нибудь помочь мне определить, из-за чего эти странные лишние персонажи выплевываются из этой функции - это заставляет меня задуматься?

Ответы [ 4 ]

5 голосов
/ 05 апреля 2011
int i,j,k;
char c = source[i++]; 
i = j = k = 0;

Вы используете i, прежде чем присвоите ему значение.Вы не можете предполагать, что автоматические переменные будут инициализированы как 0.

while (c != '\n' && c != '\0' && c != EOF) {

Поскольку c является char, оно никогда не может равняться EOF.Не имеет значения, но когда-нибудь вы увидите эту ошибку :) Вы должны использовать int для этой идиомы:

int c;

while((c=getchar()) != EOF) {
    /* process c */
}

Вы используете tempsort[] до того, как он также будет инициализирован:

        comp_c = tempsort[j];

Вы записываете лот данных обратно в массив source[]:

for (i = 0; i <= MAX_SORT_LENGTH + 1; i++) {
   source[i] = tempsort[i];
}

Я надеюсь, что массив source[] гарантирован гарантирован быть достаточно большим, чтобы содержать MAX_SORT_LENGTH данных, а не просто достаточно большим, чтобы содержать стандартную строку C.Поскольку это, вероятно, дружелюбный профессор, это, вероятно, хорошо, но я бы не сделал этого предположения легкомысленно.

И, как последний совет, каждое из этих (int) приведений бесполезно;компилятор знает, как сравнивать и делать арифметические вычисления для char переменных.:)

3 голосов
/ 05 апреля 2011

Не уверен, что это причина, но я заметил, что вы используете i до того, как он будет правильно инициализирован:

char c = source[i++]; 
i = j = k = 0;

Вы захотите перевернуть эти две строки.

2 голосов
/ 05 апреля 2011

Пара подсказок:

  • если у вас есть программа, которая отображает разные результаты на разных системах, это часто указывает на то, что она использует неинициализированные данныеФлаг «-Wall» (выводить все предупреждения) для gcc, что хорошо, но вы можете знать, что gcc может лучше обнаруживать (и предупреждать) неинициализированные переменные, если вы также используете «-O»Оптимизировать) flag

Кроме того, внимательно посмотрите на граничные условия на ваших циклах.Вы уверены, что не получаете доступ к памяти за пределами ваших массивов?Помните, что если у вас есть массив типа char x[10], допустимыми значениями являются x[0] - x[9];x[10] выходит за пределы.

2 голосов
/ 05 апреля 2011

Возможно, ошибка заключается в том, что локальная переменная не инициализируется нулем.

...