[ad_1]
- When processing regular characters (final else clause) you read additional input instead of operating over
text, i.e. instead of:
scanf("%c", &document[parano][sentno][wordno][charno]);
printf("%c\n", document[parano][sentno][wordno][charno]);
charno++;
you want to do:
document[parano][sentno][wordno][charno++] = text[i];
By the time we hit text[i] == ' ' for the first time the value of ***document is “3\n1 2\n2\n” but you wanted it to be “Learning”.
(not fixed) When processing a word (`text[i] == ‘ ‘) you expand current word, yet, you hard-code 1000 when you allocate it initially so this doesn’t make sense. Be consistent.
parano,sentno,wordno,charnois indices but same suggest they are counts. It’s not wrong just confusing and why you have towordno + 2when relloc’ing.Terminate words with `\0′.
When you process ‘ ‘ you add another word which you may or may not need which is fine. But when process a ‘.’ you look ahead to the following letter is a
\nor not. Be consistent. If you look ahead then you need to check thati + 1 < len, and it’s fragile, say, there is a stray space before the\n.(not fixed) Memory leaks. As the size of the sub-elements (paragraph, sentences and words) are private implementation details of
get_document()you will have refactor the code to make those available. I suggest:
struct document {
char ****document;
size_t paragraphs;
size_t sentences;
size_t words;
}
(not fixed) Deduplicate. Similar to the print functions, create a allocation function per type.
(not fixed, really)
get_input_text(). You split the into paragraphs then concatenate everything again into a local variable then copy it into a dynamically allocated variable:
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;
- (not fixed) Separate i/o from processing. This simplifies testing and it makes it easier to figure out what is going on. In
main(), you read a query type then 1 to 3 numbers.scanf()` tells you how many items where read so you simply do. As you don’t use the kth_ functions for anything else just combine then with 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;
...
}
(not fixed) Add error checks for the remaining
malloc(),strdup()etc.Don’t hard-code magic values (1000). I introduced the constant
WORD_LENbut you also have MAX_CHARACTERS which is kinda the same thing.(not fixed) Consider using
char *s = strpbrk(text + i, " .\n")to copy a word at a time. It will simplify\0handling, and likely to be faster than walking thetexta byte at a time, i.e.i += s - text + i, just handle thes == NULLspecial case.
valgrind is now happy other than leaks (see above):
#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", ¶graph_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 as expected:
Learning pointers is more fun.It is good to have pointers.
Learning C is fun
Learning
Btw, a whole different way of solving this is problem is keep the original input (text) then write functions to directly extract a paragraph, sentence or word from that string. If you input is huge then create an index, say, (paragraph, sentence, word) to &text[i].
1
[ad_2]
solved 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