Проблемы с указателями при построении компилятора Pascal в C - PullRequest
1 голос
/ 24 июня 2009

У меня проблемы с лексическим анализом моего компилятора Я объявил следующий указатель

char *words[29]={
        "program",
        "label",
        "integer",
        "word",
        "char",
        "byte",
        "shortint",
        "logint",
        "real",
        "single",
        "double",
        "string",
        "boolean",
        "var",
        "procedure",
        "function",
        "begin",
        "end",
        "if",
        "then",
        "else",
        "or",
        "and",
        "div",
        "not",
        "do",
        "while",
        "mod"
};
char message[30];

и затем я попытался использовать его в функции

            for(handle=0;(&words[handle] != NULL);handle++)
            {
                message = &words[handle];
                if(!strcmp(token,message))
                    message='words';
            }

Но я получаю следующие ошибки при попытке выполнить:

относительно (строка сообщения = & words [handle];): предупреждение C4047: '=' : 'char [30]' отличается по уровням косвенность от 'char **'

относительно (строка сообщения = & words [handle];): ошибка C2106: '=': левый операнд должен иметь значение l

относительно (строка сообщения = 'words';): ошибка C2015: слишком много символов в постоянная

относительно (строка сообщения = 'words';): ошибка C2106: '=': левый операнд должен быть l-значение

я не могу работать с указателями таким образом? Есть ли у вас какие-либо предложения?

Ответы [ 3 ]

3 голосов
/ 24 июня 2009

У вас есть ряд ошибок:

  • вместо & words [handle], используйте слова [ручка]
  • что вы пытаетесь сделать с помощью сообщения = 'слова'? Здесь есть как минимум 3 ошибки: строка использует двойные кавычки, а не одинарные; сообщение является константой, вы не можете изменить его; чтобы копировать строки, вам нужно использовать strcpy (), а не просто = operator
  • strcmp () возвращает 0, если строки равны; вам нужно изменить свою логику
  • вы забыли включить NULL в конец вашего массива
3 голосов
/ 24 июня 2009

Три вещи:

  1. Амперсанды (&) являются посторонними. Тип words[handle] это char *, то есть строка, так что тут у вас есть то, что вам нужно. Вам не нужно брать адрес этого char *.

  2. Вы не можете напрямую присвоить message с помощью =, так как это массив. С не очень модный язык. Вы можете изменить message на char *message, так что это указатель, а не массив; или вы можете использовать функцию strcpy(dst, src) для копирования в нее, например, так: strcpy(message, "words").

  3. Ваш цикл for ищет указатель NULL в массиве words, чтобы он знал, когда остановиться - но у вас нет NULL в массиве! Вам нужно добавить NULL до конца. Как написано, есть только обычные строки, поэтому цикл никогда не найдет искомый нулевой указатель и переместится в неизведанные зоны памяти.

Надеюсь, это поможет!

2 голосов
/ 24 июня 2009

У вас есть ряд проблем с вашим кодом. Прежде всего, вы должны объявить ваш массив ключевых слов как const char *words[]. Неправильно объявлять строковые константы как char * без const; это разрешено только для того, чтобы устаревший код все еще компилировался.

Вы не должны указывать размер массива 29 в объявлении, так как он хрупок. Вы должны просто использовать пустые скобки и позволить компилятору определить размер массива. Вы можете получить размер массива, выполнив sizeof(words)/sizeof(words[0]), который все равно будет правильным, даже если вы добавите или удалите элементы из words.

Затем ваш цикл for никогда не прекратится (хотя в какой-то момент он почти наверняка прекратит работу). Взятие адреса значения никогда не приведет к нулевому указателю, поэтому &words[handle] != NULL всегда будет истинным. Правильный способ перебора цикла - просто посчитать количество записей:

for(handle = 0; handle < sizeof(words)/sizeof(words[0]); handle++)

message объявлен как массив символов. Массивы не могут быть назначены, то есть они не являются lvalues. Если вы хотите присвоить массиву, вы должны явно скопировать в него данные с чем-то вроде strcpy() (не рекомендуется, за исключением некоторых случаев, из-за возможных переполнений буфера), strncpy(), memcpy() или strncpy_s() (доступно только в Windows).

В этом случае, однако, вам совсем не нужен массив - вы просто хотите назначить указатель. Вместо этого объявите message как const char *. С message, объявленным правильно, вы должны сделать:

const char *message;
...
message = words[handle];
if(!strcmp(token, message))
    message = "words";

В последнем утверждении вы должны использовать двойные кавычки вокруг words, чтобы сделать его строковой константой. Одинарные кавычки предназначены для односимвольных констант (например, 'A'). Хотя технически они могут содержать более одного символа, порядковый номер результирующей целочисленной константы определяется реализацией, и в данном случае это не то, что вам нужно.

Я также не совсем уверен, что вы пытаетесь сделать со строкой message = "words";. Если вы пытаетесь сделать какой-то хитрый трюк с переменной words, остановитесь прямо сейчас, это не сработает. Си не имеет никакого отражения.

...