Вы имеете следующую строку кода:
int lookup (const struct entry dictionary[], const char search[], const int entries);
Внутри главной функции. С этим связаны две основные проблемы.
Объявление функций не может появляться внутри другой функции. Линия я цитировал потребности появляться за пределами вашей основной функции следующим образом:
int lookup(.....)
//code here
int main(...)
{
//more code here
}
Даже если вы объявляете функцию «подстановки», вы никогда не определить его. Вероятно, это вызывает ошибку компоновщика. Компилятор компилирует все функции, а затем компоновщик идет, чтобы связать функции вместе (так сказать) и обнаруживает, что, хотя функция «lookup» объявлена и затем вызывается, она на самом деле нигде не существует! (насколько мне известно, функция «lookup» не существует в stdlib.h или stdio.h). Это не позволяет компоновщику выполнять свою работу.
Повторим, ваш код должен быть преобразован следующим образом:
#include <stdio.h>
#include <stdlib.h>
int lookup (const struct entry dictionary[], const char search[], const int entries)
{
//lots of code belongs in here, but that's for you to figure out :)
}
int main (int argc, char *argv[]) {
struct entry {
char word[15];
char definition[100];
};
const struct entry dictionary[100] =
{{"aardvark", "a burrowing African mammal"},
{"abyss", "a bottomless pit"},
{"acumen", "mentally sharp; keen"},
{"addle", "to become confused"},
{"aerie", "a high nest"},
{"affix", "to append; attach"},
{"agar", "a jelly made from seaweed"},
{"ahoy", "a nautical call of greeting"},
{"aigrette", "an ornamental cluster of feathers"},
{"ajar", "partially opened"}};
int entries = 10;
int entryNumber;
//**REMOVE THIS LINE** Move it up top....
//int lookup (const struct entry dictionary[], const char search[], const int entries);
if (argc != 2)
{
fprintf (stderr, "No word typed on the command line.\n");
return EXIT_FAILURE;
}
entryNumber = lookup (dictionary, argv[1], entries);
if (entryNumber != -1)
printf("%s\n", dictionary[entryNumber].definition);
else
printf("Sorry, %s is not in my dictionary.\n", argv[1]);
return EXIT_SUCCESS;
}
Я надеюсь, что это помогает. Если вы не понимаете, что делает «компоновщик» или почему это важно, оставьте комментарий, и я соответствующим образом отредактирую ответ. Понимание компоновщиков и компиляторов является одним из многих факторов, отделяющих посредственных программистов от программистов C!
Я думаю, было бы полезно на данном этапе объяснить, что такое компоновщик. Прежде чем мы дойдем до этого, важно понять, что делает ваш компилятор и что такое компилированная программа.
Основываясь на коде, опубликованном в вашем вопросе, я думаю, что можно с уверенностью предположить, что вы использовали компилятор более одного раза :). Я скажу несколько вещей, которые вы уже знаете, но держитесь со мной. Файлы «.c» и «.h» описывают алгоритмы. Эти файлы легки для людей, чтобы читать и редактировать, однако на вашем компьютере может быть трудно извлечь из них смысл. Чтобы ваш компьютер «запускал» программу в этих файлах, алгоритмы должны быть преобразованы в язык, который понимает ваш компьютер. Этот язык, называемый «машинный язык», трудно для людей писать, поэтому мы пишем на C или C++ и конвертируем наши программы на C и C++ в «машинный язык» с использованием компилятора.
Теперь функция компоновщика здесь тонкая, но очень важная. Для новичка легко подумать, что компоновщик совершенно не нужен: если компилятор преобразует C в «машинный язык», то задание закончено? ну ... не совсем.
Понимаете, каждый бит «машинного языка» в вашей скомпилированной программе имеет адрес памяти.Рассмотрим следующий пример игрушечный:
#include <stdio.h>
int addnums(int numbers[], int length)
{
int total = 0;
for(int i = 0; i < length; i++)
{
total += numbers[i];
}
return total;
}
int main(int argc, char** argv)
{
int mynums[] = {1, 2, 3, 4, 5};
int total = addnums(mynums, 5);
printf("the total of the array is %i\n", total);
return 0;
}
Если бы мы должны были смотреть на машинном коде для этой игрушечной программы, мы увидим, что каждая функция имеет начальную точку и конечную точку в памяти вашего компьютера. Это означает, что каждая функция имеет адрес, где он начинается. Когда ваш компьютер выполняет линию
int total = addnums(mynums, 5);
Он должен «прыгать» в другую часть машинного кода. «int main()» может начинаться с адреса 100, а «int addnums()» - по адресу 50. Компьютер должен выполнить машинный код по адресу 50, когда он достигнет этой строки.
Компилятор не относится к адресам функций. Он просто компилирует код и оставляет его в другой программе, чтобы поместить правильные адреса в машинный код. Если компоновщик говорит что-то вроде
symbol(s) not found
это означает, что компоновщик не знает адрес для определенной функции. Обычно это происходит потому, что данная функция никогда не была объявлена или не определена. Если линкер для получения исполняемого файла из этого кода, ваш компьютер достигнет линии
int total = addnums(mynums, 5);
и сказать: «Да ??? куда я иду ??» Без адреса для перехода к функции «int addnums()» ваш процессор будет полностью потерян.
и ваша программа будет таинственно сбой.
Линкера избавляет вас от этой боли, отбрасывая ошибку и останавливая процесс компиляции. В мои любительские дни программирования встроенных систем у меня была эта проблема несколько раз, и это был кошмар для отладки.
Надеюсь, это поможет. Скажи мне, плохо ли мое объяснение.
Где функция 'lookup' определена? –