Во-первых, не имея доступа к остальной части вашего проекта (я предполагаю, что есть несколько других файлов, содержащих некоторые функции, на которые вы ссылаетесь в своем посте), невозможно узнать, как именно вы создаете код . генератор , ограничивающий предложения синтаксическими проблемами.
Объяснение следующих ошибок из вашего поста приведено как в комментариях ниже, так и в строчных комментариях в коде внизу:
Во-первых, в вашем отредактированном разделе я не вижу, что это за функция readCode()
, потому что вы ее не включили, но если она не создает память, тогда переменная code
не может использоваться.
После объявления char (**tokenized)[LINE_LENGTH_LIMIT];
вы пытаетесь использовать элемент нулевого массива char **
без предварительного создания памяти. В лучшем случае ваша программа аварийно завершит работу во время выполнения, а еще хуже - будет работать. Это называется Не определено или Не указано поведение . (читайте о том, как использовать malloc ). Поскольку вы готовите хранилище для набора строк, вам понадобятся только два уменьшения, а не три. Либо char *[]
, либо char **
будет работать. В любом случае, они должны быть инициализированы и память создана перед использованием. Однако, поскольку вы уже знаете максимальное количество строк и максимальную длину строк, просто объявите и используйте: char tokenized[CODE_LINE_LIMIT][LINE_LENGTH_LIMIT];
.
Также объявите char *token = 0;
для использования со strtok. (см. комментарии по причине)
Кроме того, объявляйте многократно используемые переменные один раз (например, i
. См. Комментарии для причины)
Остальные, опять же, просмотрите встроенные комментарии, чтобы увидеть, как предыдущие ошибки / предупреждения были учтены в вашем коде:
static void checkDeclarations(char **code, int num_lines)
{
char *token = 0;//use with strtok
char *currentLine;
char tokenized[CODE_LINE_LIMIT][LINE_LENGTH_LIMIT] = {{0}};
int i, len; // declare multiply used variables once
for (int currentLineNum = 0; currentLineNum < num_lines; currentLineNum++) {
if (code[currentLineNum] != NULL) {
currentLine = code[currentLineNum];
//char (*tokenized)[LINE_LENGTH_LIMIT] = {0};
len = strlen(currentLine);
for( i = 0; i< len; i++ ) // corrected
//for (int i = 0; i < strlen(currentLine); i++) // don't do string comparison's in a loop
{ // and avoid comparisons of different types
// return of strlen() is an unsigned int
token = strtok(currentLine, " ");
if (token == NULL) break;
else strcpy(tokenized[i], token);
}
char *currentToken;
//for (int i = 0; i < LINE_LENGTH_LIMIT; i++) { // shadow declaration of previously declared variable
for ( i = 0; i < LINE_LENGTH_LIMIT; i++) { // corrected
currentToken = tokenized[i];
if (strcmp("***", currentToken))
break;
char (*nextToken) = tokenized[i + 1];
if (strcmp("global", currentToken)) {
if (!strcmp("character", nextToken) && !strcmp("integer", nextToken) && !strcmp("double", nextToken) && !strcmp("string", nextToken)) {
printf("Declarations: unknown data type %s at line %d", nextToken, currentLineNum);
}
}
if (strcmp("character", currentToken) || strcmp("integer", currentToken) || strcmp("double", currentToken) || strcmp("string", currentToken)) {
//char *functionName = strtok(nextToken, '('); // strtok 2nd argument requires a string, not an integer
char *functionName = strtok(nextToken, "("); // corrected
// note: calling this in a loop will be a problem. either Declare 'functionName' at top of function
// or use 'token', already declared
if (strcmp("character", functionName) || strcmp("integer", functionName) || strcmp("double", functionName) || strcmp("string", functionName) || strcmp("while", functionName) || strcmp("if", functionName) || strcmp("else", functionName) || strcmp("global", functionName) || strcmp("equal", functionName) || strcmp("nequal", functionName) || strcmp("return", functionName)) {
printf("Declarations: naming violation of %s at line %d", functionName, currentLineNum);
}
//for (int i = 0; i < strlen(functionName); i++) { // "i" has already been declared above
for ( i = 0; i < len; i++) { // corrected
if (!isalnum(functionName[i]) && (functionName[i] != '_') && (functionName[i] != '?')) {
printf("Declarations: naming violation of %s at line %d", functionName, currentLineNum);
}
}
}
}
}
}
}
Изменить адрес вопроса в комментарии ...
Возможно, вам уже известно следующее, но в вашем сообщении нет никаких указаний, поэтому я предлагаю на всякий случай следующее:
Перед назначением строки для char *str
(например, с помощью strcpy
или strcat
и т. Д.) Вы должны создать память:
int desiredStrLen = 80;
char *str = calloc(desiredStrLen + 1, 1);
if(str)// test return of calloc before trusting it worked
{
//use str
...
free(str); // always, when finished with any dynamically allocated memory, free it.
Для набора строк (например, необходимого при чтении строк файла) вы можете создать память для набора строк. Определив количество строк, а также самую длинную строку в файле, вы можете создать память, достаточную для копирования каждой строки, прочитанной из файла, в строку:
char **currentLine = Create2DStr(numLines, longestLine);
if(strings)
{
/// use currentLine (in your loop)
...
strcpy(currentLine[i], code[currentLineNum]);
...
// when finished with string collection, free it.
free2DStr(&strings, numLines);
Функции, которые я использую выше, могут быть реализованы многими способами. Я использую следующее:
char ** Create2DStr(ssize_t numStrings, ssize_t maxStrLen)
{
int i;
char **str = {0};
str = calloc(numStrings, sizeof(char *));
for(i=0;i<numStrings; i++)
{
str[i] = calloc(maxStrLen + 1, 1);
}
return str;
}
void free2DStr(char *** str, ssize_t numStrings)
{
int i;
if(!(*str)) return;
for(i=0;i<numStrings; i++)
{
free((*str)[i]);
(*str)[i] = NULL;
}
free((*str));
(*str) = NULL;
}