2015-10-15 3 views
0

У меня есть массив символов с двумя указателями, который будет хранить строки строк. Моя функция анализирует строку, считанную из файла, а затем сохраняет каждый проанализированный элемент в другой файл с именем «intermediate.txt». Я хочу, чтобы каждый проанализированный элемент имел новую строку, добавленную в конец строки, поэтому в промежуточном файле каждый проанализированный элемент находится в отдельной строке.strcat не работает при попытке добавить символ новой строки в конец массива char

Я пытаюсь использовать strcat, и, похоже, он работает нормально с каждой строкой, кроме brokenUpLine [4]. (Я намеренно пропускаю элемент в 3-м индексе). В настоящее время breakUpLine [4] в данный момент хранит «коды ошибок». Я хочу добавить новую строку в конце строки, и она продолжает сбой. Если я удалю эту строку кода, она отлично работает, но сработает, когда я ее добавлю. Может кто-то помочь мне и объяснить, почему это сбой. Вот код:

void assemblePass1(FILE * sourceF) 
{ 
    int i; 
    char line[260]; 
    char ** brokenUpLine; 
    op * opCodes = createOPtable();  
    if (opCodes == NULL) 
    { 
     printf("Error allocating memory!\n\n"); 
     return; 
    } 

    char * fn = "intermediate.txt"; 
    FILE * imfp = checkForFileErrors(fn); 
    if (imfp != NULL) 
     imfp = fopen(fn, "w+"); 
    else 
     return;        

    while (fgets(line, 260, sourceF) != NULL)  //read line from source file 
    { 
     //write current source line to intermediate file 
     fprintf(imfp, line); 
     //breaks up line into values, write each value on new line in intermediate.txt 
     brokenUpLine = breakUpLine(line);    //remember to free brokenUpLine 
     strcat(brokenUpLine[0], "\n"); 
     strcat(brokenUpLine[1], "\n"); 
     strcat(brokenUpLine[2], "\n"); 
     strcat(brokenUpLine[4], "\n");   //*crashes at this line* 
     fprintf(imfp, brokenUpLine[0]);   //write label to file 
     fprintf(imfp, brokenUpLine[1]);   //write opcode to file 
     fprintf(imfp, brokenUpLine[2]);   //write operand to file 
     fprintf(imfp, brokenUpLine[3]);   //write comments to file 
     fprintf(imfp, brokenUpLine[4]);   //write error code to file 

     for (i = 0; i < 5; i++) 
     { 
      brokenUpLine[i] = NULL; 
      free(brokenUpLine[i]); 
     } 

     free(brokenUpLine); 
     break;    //for testing 
    } 

    free(opCodes); 
    fclose(imfp); 
    printf("Opening file was a success!\n\n"); 
} 

Вот breakUpLine():

char ** breakUpLine(char * line) 
{ 
    int row = 5, cols = 150, i; 
    char * string = NULL; 
    char ** arr = (char**)malloc(row * sizeof(char*)); //allocate 5 rows of memory (label(0), opcode(1), operand(2), comment(3), error code(4)) 
    for (i = 0; i < row; i++) 
     arr[i] = (char*)malloc(cols * sizeof(char)); //allocates 150 columns to store a string per row 

    char * token = NULL; 
    i = 0; 

    if (line[0] == ' ')     //if there is no label, assign to the label row an empty space 
    { 
     arr[0] = " ";     //store a space in label column to indicate it has no label 
     i = 1; 
    } 

    token = strtok(line, " \t");  //get first token; break up by spaces or tabs 
    if (token[0] == '.')     //if a period is found at beginning of line, then the line is an entire comment 
    { 
     token = strtok(NULL, "\n");  //store entire comment sentence including the spaces, so update token delimeter to a newline character 
     arr[0] = "."; 
     arr[1] = "\n"; 
     arr[2] = "\n"; 
     arr[3] = token;     //store comment in comment row 
     arr[4] = NULL;     //error code will be 0 or NULL if no error was detected 
     return arr;      //remember to free arr in assemblePass1() 
    } 

    arr[i++] = token;     //store token in appropriate row 
    while (token != NULL && i != 3)  
    { 
     token = strtok(NULL, " \t"); 
     arr[i++] = token; 
     //totest:printf("%s\n", arr[i-2]); 
    } 

    //totest:printf("%s\n", arr[i - 1]); 
    token = strtok(NULL, "\t");  //process comments 
    arr[i] = token;     //store comment in comment column 
    arr[4] = "Error code";     //error code will go here 

    return arr; 
} 
+1

Независимо от того, что делает 'breakUpLine', он может выделять недостаточно памяти. это, по-видимому, происходит для других частей, потому что после этого вы записываете в память, что может быть просто «промежутком». Поэтому, пожалуйста, покажите 'breakUpLine'. – usr2564301

+1

Несвязанный сбой, но ваш код очистки должен 'free (brokenUpLine [i])' * before * setting 'brokenUpLine [i] = NULL;'. – keithmo

+0

@Jongware Я добавил 'breakUpLine()'. –

ответ

3

Вы аварии из-за этой линии:

arr[4] = NULL;     //error code will be 0 or NULL if no error was detected 

, поскольку впоследствии вы пытаетесь strcat к этому NULL указатель здесь:

strcat(brokenUpLine[4], "\n");   //*crashes at this line* 

Возможно, это должно было быть:

strcat(brokenUpLine[3], "\n"); 

????

У вас также есть проблемы здесь:

arr[0] = "."; 
    arr[1] = "\n"; 
    arr[2] = "\n"; 

Они должны быть:

strcpy(arr[0], "."); 
    strcpy(arr[1], "\n"); 
    strcpy(arr[2], "\n"); 

иначе у вас есть (а) Неопределенное поведение, когда вы пытаетесь strcat этих строк, (б) три памяти утечки и (в) еще более неопределенное поведение, если вы позже попытаетесь установить free() эти строки.

+0

Ах спасибо! Кроме того, почему назначение неправильно? Почему я должен использовать strcpy? Спасибо, я новичок в C, поэтому хочу узнать эти вещи. –

+0

Вы не можете назначать строки с '=' в C - вы можете назначать только * указатели *, что вы делаете в своем коде. Таким образом, это эффективно отбрасывает исходное распределение памяти (которое является утечкой памяти) и заменяет указатель указателем на строковый литерал. TL; DR: используйте 'strcpy' для назначения строк в C, а не' = '. –

+0

Хорошо, спасибо, что поняли это для меня. Я исправлю код:] –