почему длинные строки, когда я делаю классическую c посылку на символ ** cra sh программу - PullRequest
1 голос
/ 04 мая 2020

У меня редкая проблема с этой программой в C, и я действительно не понимаю, почему я получаю cra sh, когда ставлю длинные строки, я думаю, что это может быть функцией strtok, но я действительно не знаю почему?

Вот это main с минимальным воспроизведенным кодом, проверенным мной:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

char **str_split(char *a_str, const char a_delim) {
    char **result    = 0;
    size_t count     = 0;
    char *tmp        = a_str;
    char *last_comma = 0;
    char delim[2];
    delim[0] = a_delim;
    delim[1] = 0;

    /* Count how many elements will be extracted. */
    while (*tmp) {
        if (a_delim == *tmp) {
            count++;
            last_comma = tmp;
        }
        tmp++;
    }

    /* Add space for trailing token. */
    count += last_comma < (a_str + strlen(a_str) - 1);

    /* Add space for terminating null string so caller
       knows where the list of returned strings ends. */
    count++;

    result = malloc(sizeof(char *) * count);

    if (result) {
        size_t idx  = 0;
        char *token = strtok(a_str, delim);

        while (token) {
            assert(idx < count);
            *(result + idx++) = strdup(token);
            token = strtok(0, delim);
        }
        assert(idx == count - 1);
        *(result + idx) = 0;
    }
    return result;
}

char ***text_to_array(char *path) {
    //Inputs T01/comprobar_senales/ctrlc_small.txt
    char *palabra = path;
    printf("%s", palabra);
    FILE *fp = fopen(palabra, "r");
    if (fp == NULL) {
        perror("Unable to open file!");
        exit(1);
    }

    //contador
    int ch = 0;
    int lines = 0;
    while (!feof(fp)) {
        ch = fgetc(fp);
        if (ch == '\n') {
            lines++;
        }
    }
    lines++;
    fclose(fp);
    printf("numb of lines ");
    printf("%d\n", lines);
    //contador

    fp = fopen(palabra, "r");   
    char chunk[255];//recordar mejor este lector

    char ***list_with_text = malloc(lines * sizeof(char**));
    //char list_with_text[lines];

    // Store the chunks of text into a line buffer
    int count_of_lines = 0;
    size_t len = sizeof(chunk);
    char *line = malloc(len);
    char *aux_line = malloc(len);
    char **aux_for_split;
    if (line == NULL) {
        perror("Unable to allocate memory for the line buffer.");
        exit(1);
    }

    // "Empty" the string
    line[0] = '\0';

    while (fgets(chunk, sizeof(chunk), fp) != NULL) {
        // Resize the line buffer if necessary
        size_t len_used = strlen(line);
        size_t chunk_used = strlen(chunk);

        if (len - len_used < chunk_used) {
            len *= 2;
            if ((line = realloc(line, len)) == NULL) {
                perror("Unable to reallocate memory for the line buffer.");
                free(line);
                exit(1);
            }
        }
        // Copy the chunk to the end of the line buffer
        strncpy(line + len_used, chunk, len - len_used);
        len_used += chunk_used;
        fputs(line, stdout);
        strcpy(aux_line, line);
        aux_for_split = str_split(aux_line, ' ');
        list_with_text[count_of_lines] = aux_for_split; //char**
        count_of_lines++;
        // Check if line contains '\n', if yes process the line of text
        if (line[len_used - 1] == '\n') {
            printf("%d", strlen(line));
            fputs("|*\n", stdout);
            // "Empty" the line buffer
            line[0] = '\0';
        } else {
            fputs(line, stdout);
        }
    }

    fclose(fp);
    free(line);
    //printf(list_with_text);
    printf("\nMax line size: %d\n", len);

    return list_with_text;
}

char ***text_to_array(char *);

int main(int argc, char *argv[]) {
    char ***texto_en_lista = text_to_array("input.txt");
    printf("%s\n", texto_en_lista[0][0]);
    printf("bye");
}

Я пробовал этот ввод:

3
IchottMano 0 400 9 9 8 7 7 2 2 4 7 6 2 2 8 5 2 5 10 8 7 9 9 7 8 2 9 1 2 8 9 4 1 3 4 7 3 1 3 5 4 3 2 2 9 5 2 9 1 9 10 4 2 7 5 4 8 5 8 3 9 9 7 2 6 4 4 8 5 4 4 3 7 2 6 5
Jaluco 100 300 7 1 2 3 3 7 1 1 7 2 9 6 3 5 4 9 6 8 2 2 8 3 5 8 9 7 5 5 9 4 3 4 9 1 9 7 2 2 9 10 2 10 3 4 1 1 10 5 1 10 4 9 1 6 5 7 2 8 10 3 9 4 2 2 2 1 9 2 7 6 7 10 7 2 4 4 10 7 7 2 3 5 9 3 7 2 7 5 9 2 1 4 8 3 1 4 5 6 5 4 5 5 8 1 9 3 1 8 9 6 6 7 2 8
Mtenis96 200 500 7 9 5 9 2 4 3 8 10 9 2 3 9 7 2 4 8 7 1 1 7 4 3 9 9 6 5 7 10 2 10 7 5 3 2 6 10 10 4 5 4 7 8 3 2 6 10 10 1 4 2 2 2 6 9 2 4 8 5 2 10 9 3 9 8 7 3 2 1 4 2 4 7 8 4 6 9 4 3 9 4 5 2 1 1 2 6 6 4 3 7 4 7 3 4 5 6 5 4 5 5 8 1 9 3 1 8 9 6 6 7 2 8 1 2 3 4 1 2 3 4 1 2 3

и единственная подсказка, которая у меня есть, заключается в том, что если я добавлю одно число (пробел, а затем число) в последнюю строку этого ввода программы cra sh, выполнение не даст мне больше информации о cra sh за исключением этого окна:

enter image description here

1 Ответ

1 голос
/ 09 мая 2020

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

char** str_split(char* a_str, const char a_delim)
{
    char** result    = 0;
    size_t count     = 0;
    char* tmp        = a_str;
    char* last_comma = 0;
    char delim[2];
    delim[0] = a_delim;
    delim[1] = 0;

    /* Count how many elements will be extracted. */
    while (*tmp)
    {
        if (a_delim == *tmp)
        {
            count++;
            last_comma = tmp;
        }
        tmp++;
    }

    /* Add space for trailing token. */
    count += last_comma < (a_str + strlen(a_str) - 1);

    /* Add space for terminating null string so caller
       knows where the list of returned strings ends. */
    count++;

    result = malloc(sizeof(char*) * count);

    if (result)
    {
        size_t idx  = 0;
        char* token = strtok(a_str, delim);

        while (token)
        {
            assert(idx < count);
            *(result + idx++) = strdup(token);
            token = strtok(0, delim);
        }
        assert(idx == count - 1);
        *(result + idx) = 0;
    }

    return result;
}


char ***text_to_array(char *path){

    char *palabra = path;
    FILE *fp = fopen(palabra, "r");
    if(fp == NULL) {
        perror("Unable to open file!");
        exit(1);
    }

    //contador de lineas
    int ch = 0;
    int lines = 0;
    while(!feof(fp))
    {
        ch = fgetc(fp);
        if(ch == '\n')
        {
            lines++;
        }
    }
    lines++;
    fclose(fp);
    //contador de lineas
    printf("numero de lineas %d",lines);
    fp = fopen(palabra, "r");   
    char chunk[255];
    char ***list_with_text = malloc(lines*sizeof(char**));
    int i;  
    // Store the chunks of text into a line buffer
    int count_of_lines = 0;
    size_t len = sizeof(chunk);
    char *line = malloc(len);
    char *aux_line = malloc(len);
    char **aux_for_split;
    // "Empty" the string
    line[0] = '\0';
    printf("empezo el webeo mierd222a");
    while(fgets(chunk, sizeof(chunk), fp) != NULL) {
        size_t len_used = strlen(line);
        size_t chunk_used = strlen(chunk);
        if(len - len_used < chunk_used) {
            len *= 2;
            //printf("agrandando buffer \n");
            if((line = realloc(line, len)) == NULL) {
                perror("Unable to reallocate memory for the line buffer.");
                free(line);
                exit(1);
            }
        }  
        // Copy the chunk to the end of the line bufferr
        strncpy(line + len_used, chunk, len - len_used);
        len_used += chunk_used;
        //all that it was here now i did in the next if
        if(line[len_used - 1] == '\n') {
            aux_line = realloc(aux_line,len);//HERE is where i put all the past code to have a dinamic reader
            strcpy(aux_line,line);//HERE is where i put all the past code to have a dinamic reader
            list_with_text[count_of_lines]=str_split(aux_line,' ');//HERE is where i put all the past code to have a dinamic reader
            count_of_lines++;//HERE is where i put all the past code to have a dinamic reader
            line[0] = '\0';   
        }else{

        }        
    }
    fclose(fp);
    free(line);
    printf("\nMax line size: %d\n", len);
    return list_with_text;  
}




char ***text_to_array(char*);
int main(int argc, char *argv[]) {
    char ***texto_en_lista = text_to_array("input.txt");
    printf("%s\n", texto_en_lista[0][0]);
    printf("bye");
}

проблема была здесь в этой части кода:

aux_line = realloc(aux_line,len);//HERE is where i put all the past code to have a dinamic reader
                strcpy(aux_line,line);//HERE is where i put all the past code to have a dinamic reader
                list_with_text[count_of_lines]=str_split(aux_line,' ');//HERE is where i put all the past code to have a dinamic reader
                count_of_lines++;//HERE is where i put all the past code to have a dinamic reader

потому что я все время переписывал переменную, которая содержит все буферы с другой частью данных tge, которые я извлек из файла (255 - это размер буфера, другими словами, количество символов, которые я извлекаю из файла чтобы сохранить его в другом var, чтобы прочитать все строки)

...