簡體   English   中英

我已經連續兩天在這個問題上討論文件,但沒有用。 不想作弊,你能指出問題嗎

[英]i have been on this question for quaring the document for two days straight, and it is not working. don't want to cheat, can you point the problem

我無法調試正在發生的事情。 代碼似乎是正確的,但我對指針的指針不熟悉,這里有 4 個系列。

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

#define MAX_CHARACTERS 1005
#define MAX_PARAGRAPHS 5

char *kth_word_in_mth_sentence_of_nth_paragraph(char ****document, int k, int m, int n) {
    return *(*(*(document + n - 1) + m - 1) + k - 1);
}

char **kth_sentence_in_mth_paragraph(char ****document, int k, int m) { 
    return (*(*(document + m - 1) + k - 1));
}

char ***kth_paragraph(char ****document, int k) {
    return *(document + k - 1);
}

char ****get_document(char *text) {
    /* allocating memory */
    int len = strlen(text);
    /* allocate memory for each component first */
    char ****document = malloc(sizeof(char ***));
    char ***paragraph = malloc(sizeof(char **));
    char **sentence = malloc(sizeof(char *));
    char *word = malloc(sizeof(char) * 1024);
    /* connect all the components to point in the sequence that is required */
    *document = paragraph;
    *paragraph = sentence;
    *sentence = word;
    /* declare some numbers as iterators for the words, sentences,etc. */
    int parano = 0;
    int sentno = 0;
    int wordno = 0;
    int charno = 0;
    /* now iterate over the text filling and expanding the document at the same time */
    /*----------------------------------------------------------------------------------------------------*/
    /* feeding data in those spaces */
    for (int i = 0; i < len; i++) {
        if (text[i] == ' ') {
            /* wrapping the current word, that is, resizing to len + 1 */
            char *current_word = *(*(*(document + parano) + sentno) + wordno);
            current_word = realloc(current_word, strlen(current_word) + 1);
            /*  resizing the current sentence to add another word*/
            char **current_sentence = (*(*(document + parano) + sentno));
            current_sentence = realloc(current_sentence, sizeof(char *) * (wordno + 2));
            
            wordno++;
            charno = 0;
            /* allocating space to that new char * / word that has been created in the same sentence */
            *(*(*(document + parano) + sentno) + wordno) = malloc(sizeof(char) * 1000);
        }
        else if (text[i] == '.') {
            /* wrapping of the current word has to be done anyways */
            char *current_word1 = *(*(*(document + parano) + sentno) + wordno);
            current_word1 = realloc(current_word1, strlen(current_word1) + 1);
            charno = 0;
            
            if (text[i + 1] != '\n') {
                /* the paragraph does not change, and the sentence ends */
                /* resize that paragraph for adding another sentence */
                char ***current_para = *(document + parano);
                current_para = realloc(current_para, sizeof(char **) * (sentno + 2));
                sentno++;
                wordno = 0;
                /* allocating word to that sentence */
                *(*(document + parano) + sentno) = malloc(sizeof(char *));
                /* allocating space for that word */
                *(*(*(document + parano) + sentno) + wordno) = malloc(sizeof(char) * 1000);
            } else {
                /*  if this is the last sentence of this paragraph*/
                wordno = 0;
                charno = 0;
                sentno = 0;
            }
        }
        else if (text[i] == '\n') {
            /* paragraph has changed */
            /* add another paragraph to the document */
            document = realloc(document, sizeof(char ***) * (parano + 2));
            parano++;
            /* add sentence to that paragraph */
            (*(document + parano) ) = malloc(sizeof(char **));
            /* add a word to that paragrapgh */
            (*(*(document + parano) + sentno)) = malloc(sizeof(char *));
            /* allocate space for that word */
            *(*(*(document + parano) + sentno) + wordno) = malloc(sizeof(char) * 1000);
        } else {
            scanf("%c", *(*(*(document + parano) + sentno) + wordno) + charno);
            printf("%c\n", **(*(*(document + parano) + sentno) + wordno) + charno);
            charno++;
        }
    }
    return document;
}

char *get_input_text() {    
    int paragraph_count;
    scanf("%d", &paragraph_count);

    char p[MAX_PARAGRAPHS][MAX_CHARACTERS], doc[MAX_CHARACTERS];
    memset(doc, 0, sizeof(doc));
    getchar();
    for (int i = 0; i < paragraph_count; i++) {
        scanf("%[^\n]%*c", p[i]);
        strcat(doc, p[i]);
        if (i != paragraph_count - 1)
            strcat(doc, "\n");
    }

    char *returnDoc = (char *)malloc((strlen(doc)+1) * (sizeof(char)));
    strcpy(returnDoc, doc);
    return returnDoc;
}

void print_word(char *word) {
    printf("%s", word);
}

void print_sentence(char **sentence) {
    int word_count;
    scanf("%d", &word_count);
    for (int i = 0; i < word_count; i++) {
        printf("%s", sentence[i]);
        if (i != word_count - 1)
            printf(" ");
    }
} 

void print_paragraph(char ***paragraph) {
    int sentence_count;
    scanf("%d", &sentence_count);
    for (int i = 0; i < sentence_count; i++) {
        print_sentence(*(paragraph + i));
        printf(".");
    }
}

int main() {
    char *text = get_input_text();
    char ****document = get_document(text);

    int q;
    scanf("%d", &q);

    while (q--) {
        int type;
        scanf("%d", &type);

        if (type == 3) {
            int k, m, n;
            scanf("%d %d %d", &k, &m, &n);
            char *word = kth_word_in_mth_sentence_of_nth_paragraph(document, k, m, n);
            print_word(word);
        }
        else if (type == 2) {
            int k, m;
            scanf("%d %d", &k, &m);
            char **sentence = kth_sentence_in_mth_paragraph(document, k, m);
            print_sentence(sentence);
        } else {
            int k;
            scanf("%d", &k);
            char ***paragraph = kth_paragraph(document, k);
            print_paragraph(paragraph);
        }
        printf("\n");
    }     
}

這是 Hackerrank 上針對 C 語言的問題之一。 鏈接到問題hacker rank question my profile

顯示已中止, realloc無效大小 在過去的兩天里我找不到任何東西。

問題的輸入

2
Learning C is fun.
Learning pointers is more fun.It is good to have pointers.
3
1 2
2
5
6
2 1 1
4
3 1 1 1

預計 output

Learning pointers is more fun.It is good to have pointers.
Learning C is fun
Learning
  1. 在處理常規字符(最后的 else 子句)時,您會讀取額外的輸入而不是對text進行操作,即而不是:
                scanf("%c", &document[parano][sentno][wordno][charno]);
                printf("%c\n", document[parano][sentno][wordno][charno]);
                charno++;

你想做:

                document[parano][sentno][wordno][charno++] = text[i];

當我們第一次點擊text[i] == ' '時, ***document的值是“3\n1 2\n2\n”,但你希望它是“Learning”。

  1. (不固定)當處理一個單詞 (`text[i] == ' ') 時,您擴展了當前單詞,但是,當您最初分配它時,您硬編碼了 1000,所以這沒有意義。 始終如一。

  2. sentnoparanowordnocharno是索引,但同樣表明它們是計數。 混淆並沒有錯,為什么在重新定位時必須使用wordno + 2

  3. 以‘\0’結束單詞。

  4. 當你處理 ' ' 時,你添加了另一個你可能需要也可能不需要的詞,這很好。 但是當處理一個'。' 你先看看后面的字母是不是\n 始終如一。 如果你向前看,那么你需要檢查i + 1 < len ,它很脆弱,比如說,在\n之前有一個雜散空間。

  5. (未修復)Memory 泄漏。 由於子元素(段落、句子和單詞)的大小是get_document()的私有實現細節,您將重構代碼以使其可用。 我建議:

struct document {
   char ****document;
   size_t paragraphs;
   size_t sentences;
   size_t words;
}
  1. (不固定)重復數據刪除。 與打印功能類似,為每種類型創建分配 function。

  2. (不固定,真的) get_input_text() 您將其拆分為段落,然后將所有內容再次連接到一個局部變量中,然后將其復制到一個動態分配的變量中:

   char *str = malloc(BUFFER_LEN);
   for(size_t i = 0, l = 0; l < lines && i + 1 < BUFFER_LEN; i += strlen(str + i)) {
       int rv = fgets(str + i, BUFFER_LEN - i, stdin);
       if(!rv) {
          // handle error
          break;
       }
   }
   return s;
  1. (不固定)將 I/O 與處理分開。 這簡化了測試,並且更容易弄清楚發生了什么。 main(), you read a query type then 1 to 3 numbers. scanf()` 告訴您讀取了多少項目,因此您只需執行即可。 由於您不將 kth_ 函數用於任何其他用途,因此只需將其與 print_ funci 結合使用
    int n = scanf("%d %d %d %d", &type, &p, &s, &w);
    switch(type) {
        case 1:
            if(n != 2) {
              // handle error
            }
            print_paragraph(document, p);
            break;
        ...
    }
  1. (未修復)為剩余的malloc()strdup()等添加錯誤檢查。

  2. 不要硬編碼魔法值 (1000)。 我介紹了常量WORD_LEN ,但您也有 MAX_CHARACTERS,這是一回事。

  3. (不固定)考慮使用char *s = strpbrk(text + i, ".\n")一次復制一個單詞。 它將簡化\0處理,並且可能比一次一個字節地遍歷text更快,即i += s - text + i ,只需處理s == NULL特殊情況。

valgrind 現在很高興除了泄漏(見上文):

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CHARACTERS 1005
#define MAX_PARAGRAPHS 5
#define WORD_LEN 1000

char *kth_word_in_mth_sentence_of_nth_paragraph(char ****document, int p, int s, int w) {
    return document[p - 1][s - 1][w - 1];
}

char **kth_sentence_in_mth_paragraph(char ****document, int p, int s) {
    return document[p - 1][s - 1];
}

char ***kth_paragraph(char ****document, int p) {
    return document[p - 1];
}

char ****get_document(char* text) {
    char ****document = malloc(sizeof ***document);
    *document = malloc(sizeof **document);
    **document = malloc(sizeof *document);
    ***document = malloc(WORD_LEN);

    /*  declare some numbers as iterators for the words, sentences,etc.*/
    int parano = 0;
    int sentno = 0;
    int wordno = 0;
    int charno = 0;
    /*  now iterate over the text filling and expanding the document at the same time*/
    /*----------------------------------------------------------------------------------------------------*/
    /*  feading data in those spaces*/
    size_t len = strlen(text);
    for (size_t i = 0; i < len; i++) {
        switch(text[i]) {
            case ' ': {
                document[parano][sentno][wordno][charno] = '\0';

                wordno++;
                char **words = realloc(
                    document[parano][sentno],
                    (wordno + 1) * sizeof *document[parano][sentno]
                );
                if(!words) {
                    printf("realloc of words failed\n");
                    exit(1);
                }
                document[parano][sentno] = words;
                document[parano][sentno][wordno] = malloc(WORD_LEN);
                charno = 0;
                break;
            }
            case '.': {
                document[parano][sentno][wordno][charno] = '\0';

                sentno++;
                char ***sentences = realloc(
                    document[parano],
                    (sentno + 1) * sizeof *document[parano]
                );
                if(!sentences) {
                    printf("realloc of sentences failed\n");
                    exit(1);
                }
                document[parano] = sentences;
                document[parano][sentno] = malloc(sizeof **document);
                wordno = 0;
                document[parano][sentno][wordno] = malloc(WORD_LEN);
                charno = 0;
                break;
            }
            case '\n': {
                document[parano][sentno][wordno][charno] = '\0';

                parano++;
                char ****paragraphs = realloc(
                    document,
                    (parano + 1) * sizeof *document
                );
                if(!paragraphs) {
                    printf("realloc of paragraphs failed\n");
                    exit(1);
                }
                document = paragraphs;
                document[parano] = malloc(sizeof ***document);
                sentno = 0;
                document[parano][sentno] = malloc(sizeof **document);
                wordno = 0;
                document[parano][sentno][wordno] = malloc(WORD_LEN);
                charno = 0;
                break;
            }
            default: // character
                document[parano][sentno][wordno][charno++] = text[i];
        }
    }
    return document;
}

char *get_input_text() {
    int paragraph_count;
    scanf("%d", &paragraph_count);
    char p[MAX_PARAGRAPHS][MAX_CHARACTERS];
    char doc[MAX_CHARACTERS];
    memset(doc, 0, sizeof doc);
    getchar();
    for (int i = 0; i < paragraph_count; i++) {
        scanf("%[^\n]%*c", p[i]);
        strcat(doc, p[i]);
        if (i != paragraph_count - 1)
            strcat(doc, "\n");
    }
    return strdup(doc);
}

void print_word(char *word) {
    printf("%s", word);
}

void print_sentence(char **sentence) {
    int word_count;
    scanf("%d", &word_count);
    for(int i = 0; i < word_count; i++){
        print_word(sentence[i]);
        if(i + 1 != word_count)
            printf(" ");
    }
}

void print_paragraph(char ***paragraph) {
    int sentence_count;
    scanf("%d", &sentence_count);
    for (int i = 0; i < sentence_count; i++) {
        print_sentence(paragraph[i]);
        printf(".");
    }
}

int main() {
    char *text = get_input_text();
    char ****document = get_document(text);
    int q;
    scanf("%d", &q);
    while (q--) {
        int type;
        scanf("%d", &type);
        switch(type) {
            case 1: {
                int p;
                scanf("%d", &p);
                print_paragraph(kth_paragraph(document, p));
                break;
            }
            case 2: {
                int p, s;
                scanf("%d %d", &p, &s);
                print_sentence(kth_sentence_in_mth_paragraph(document, p, s));
                break;
            }
            case 3: {
                int p, s, w;
                scanf("%d %d %d", &p, &s, &w);
                print_word(kth_word_in_mth_sentence_of_nth_paragraph(document, p, s, w));
                break;
            }
            default:
                printf("error\n");
        }
        printf("\n");
    }
    free(text);
}

Output 如預期:

Learning pointers is more fun.It is good to have pointers.
Learning C is fun
Learning

順便說一句,解決這個問題的一種完全不同的方法是保留原始輸入( text ),然后編寫函數直接從該字符串中提取段落、句子或單詞。 如果您輸入的內容很大,則創建一個索引,例如,( paragraph , sentence , word ) 到&text[i]

終於做到了。 非常感謝@allanwind 的支持

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<assert.h>
#define MAX_CHARACTERS 1005
#define MAX_PARAGRAPHS 5

char *kth_word_in_mth_sentence_of_nth_paragraph(char ****document, int k, int m, int n) {
    return *(*(*(document + n - 1) + m - 1) + k - 1);
}

char **kth_sentence_in_mth_paragraph(char ****document, int k, int m) { 
    return (*(*(document + m - 1) + k - 1));
}

char ***kth_paragraph(char ****document, int k) {
    return *(document + k - 1);
}

char ****get_document(char *a) 
{
    int len = strlen(a);
    char ****document = malloc(sizeof(char ***) * MAX_PARAGRAPHS);
    int parano = 0;
    char ***paragraph = malloc(sizeof(char **) * MAX_CHARACTERS);
    int sentno = 0;
    char **sentence = malloc(sizeof( char *) * MAX_CHARACTERS);
    int wordno = 0;
    char *word = malloc(sizeof(char ) * MAX_CHARACTERS);
    int charno = 0;
    
    for (int i = 0; i < len; i++)
    {
        /*  after this way, try to learn switch conditionals*/
        if (a[i] == ' ')
        {
            /*  if find a space, that is there are more words within the same sentence*/
            /*  close the word*/
            word[charno] = '\0';
            /*  add the word to the sentence*/
            sentence[wordno] = word;
            wordno++;
            charno = 0;
            /*  create another word*/
            char *tmp = malloc(sizeof(char) * MAX_CHARACTERS);
            /*  if the word got space without errors,*/
            if (tmp != NULL)
            {
                word = tmp;
            }
        }
        else if (a[i] == '.')
        {
            // terminate the word
            word[charno] = '\0';
            // add word to the sentence
            sentence[wordno] = word;
            wordno = 0;
            charno = 0;
            //  add sentence to paragraph
            paragraph[sentno] = sentence; 
               
            if (i != len - 1)
            {
                sentno++;
                // allocate space for new sentence, as it is not the end
                char **tmp1 = malloc(sizeof(char *) * MAX_CHARACTERS);
                if (tmp1 != NULL)
                {
                    sentence = tmp1;
                }
                // allocate space for new word
                char *tmp2 = malloc(sizeof(char) * MAX_CHARACTERS);
                if (tmp2 != NULL)
                {
                    word = tmp2;
                }
                
            }
            else  
            {
                document[parano] = paragraph;
            }
        }
        else if (a[i] == '\n')
        {
            // add paragraph to the document
            document[parano] = paragraph;
            parano++;
            // allocate memory for another paragraph
            char ***tmp3 = malloc(sizeof(char **) * MAX_CHARACTERS);
            if (tmp3 != NULL)
            {
                paragraph = tmp3;
            }
            charno = 0;
            wordno = 0;
            sentno = 0;
        }
        else  
        {
            /*  step 1 read the text into the word char by char*/
            word[charno] = a[i];
            charno++;
        }
    }
    
    return document;
}

char* get_input_text() {    
    int paragraph_count;
    scanf("%d", &paragraph_count);

    char p[MAX_PARAGRAPHS][MAX_CHARACTERS], doc[MAX_CHARACTERS];
    memset(doc, 0, sizeof(doc));
    getchar();
    for (int i = 0; i < paragraph_count; i++) {
        scanf("%[^\n]%*c", p[i]);
        strcat(doc, p[i]);
        if (i != paragraph_count - 1)
            strcat(doc, "\n");
    }

    char* returnDoc = (char*)malloc((strlen (doc)+1) * (sizeof(char)));
    strcpy(returnDoc, doc);
    return returnDoc;
}

void print_word(char* word) {
    printf("%s", word);
}

void print_sentence(char** sentence) {
    int word_count;
    scanf("%d", &word_count);
    for(int i = 0; i < word_count; i++){
        printf("%s", sentence[i]);
        if( i != word_count - 1)
            printf(" ");
    }
} 

void print_paragraph(char*** paragraph) {
    int sentence_count;
    scanf("%d", &sentence_count);
    for (int i = 0; i < sentence_count; i++) {
        print_sentence(*(paragraph + i));
        printf(".");
    }
}

int main() 
{
    char* text = get_input_text();
    char**** document = get_document(text);

    int q;
    scanf("%d", &q);

    while (q--) {
        int type;
        scanf("%d", &type);

        if (type == 3){
            int k, m, n;
            scanf("%d %d %d", &k, &m, &n);
            char* word = kth_word_in_mth_sentence_of_nth_paragraph(document, k, m, n);
            print_word(word);
        }

        else if (type == 2){
            int k, m;
            scanf("%d %d", &k, &m);
            char** sentence = kth_sentence_in_mth_paragraph(document, k, m);
            print_sentence(sentence);
        }

        else{
            int k;
            scanf("%d", &k);
            char*** paragraph = kth_paragraph(document, k);
            print_paragraph(paragraph);
        }
        printf("\n");
    }     
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM