1

I want to get from user multiple line strings.

How I can do that?

User doesn’t know beforehand how many “paragraphs” wants.

User Input (example_1):

Hello! (clicks Enter button)                                                          
World! (clicks Enter button)                                       
(clicks Enter button) 

Output:

Hello!                                                                                
World! 

User Input (example_2):

(clicks Enter button)

Output:

(nothing)
  • Why are you reading a char inside your for loop max_index-1 times? What's the purpose of paragraphs? From what I understand from the problem description, you want to read n strings and store these inside a 1D array. Is that it? – CRM Apr 05 '20 at 10:40

2 Answers2

1

There are some notes here:

1. You could have used getline() function instead of scanning characters one by one.

2. Assuming that for now we want to use scanf, you might not now the paragraph's length beforehand, so its better to use a linked list of lines in which you allocate memory dynamically. Here is a working example:

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

typedef struct _line{
    char * chars_in_line; 
    struct _line * next_line; 
}line; 

void fill_paragraph_lines(line * first_line , int max_size){

    first_line->chars_in_line = (char *)malloc(max_size * sizeof(char)); 
    first_line->next_line = NULL; 

    line * current_line = first_line;
    int i; 
    char aux = '\0'; 

    while(1){

        for(i = 0 ; i < max_size ; i++){
            if(aux == '\0'){
                printf("enter a character: "); 
                scanf(" %c" , &aux);
            }

            // if the received character is not '\n' put that in line 
            if(aux != '\n'){
                current_line->chars_in_line[i] = aux;
                aux = '\0'; 
            } 

            // if you receive \n as an input character, set the ending \0 and break from for loop
            else{
                current_line->chars_in_line[i] = '\0';
                aux = '\0';
                break; 
            }

            // reset aux character to its initial value
            aux = '\0'; 

            // if you reach max_size also end the string with '\0', no matter what character you received from user
            if(i == max_size - 1){
                current_line->chars_in_line[i] = '\0';
                printf("\nmax line characters reached\n"); 
                aux = '\0';
            } 
        }

        // the user can end a paragraph by inputting \n, when previous line is completed
        char possible_paragraph_ending;
        printf("enter a character: ");  
        scanf(" %c" , &aux); 
        if(aux == '\n')
            return; 

        // if the user inputs another character, start a new line 
        line * new_line = (line*)malloc(sizeof(line)); 
        new_line -> chars_in_line = (char *)malloc(max_size * sizeof(char));
        new_line ->next_line = NULL ;
        // chain the new line to the previous lines and move the pointer current line to the 
        // newly created line  
        current_line->next_line = new_line; 
        current_line = new_line; 
    } 
}


void destroy_paragraph(line * first_line){
    if(first_line == NULL)
        return ; 

    line * traverse_line = (line *)first_line->next_line; 
    line * dealloc_line = first_line; 

    while(1){
        free(dealloc_line->chars_in_line); 
        free(dealloc_line); 

        if(traverse_line == NULL)
            return; 

        dealloc_line = traverse_line; 
        traverse_line = dealloc_line->next_line; 
    }
}

void print_paragraph(line * first_line){
    line * traverse_line = first_line; 

    while(traverse_line != NULL){
        printf("%s\n" , traverse_line->chars_in_line); 
        traverse_line = traverse_line->next_line; 
    }

}

int main() {

    line * first_line = (line *)malloc(sizeof(line));
    fill_paragraph_lines(first_line , 10) ; 


    print_paragraph(first_line); 
    destroy_paragraph(first_line); 



    return 0 ; 
}

In the code above, you need to hit enter after each character in a line. If you want to end a line, you have to press Return 2 times consecutively and you need to press Return 3 times to end a paragraph.
When a new line needs to be generated, memory is dynamically allocated. destroy_paragraph() needs to be called to free memory.

Keyarash
  • 11
  • 3
  • [Using fflush(stdin)](https://stackoverflow.com/questions/2979209/using-fflushstdin) is incorrect. – anastaciu Apr 05 '20 at 13:23
  • Could you elaborate on that pls? I tested the code from command line, and fflush is there to remove the \n when you enter a number. – Keyarash Apr 05 '20 at 13:53
  • Did you see the link I left you? `fflush` is for `stdout`, not `stdin`. To remove `'\n'`, a space before %c would suffice, `" %c"` , there are several post in this site about this, like [this one](https://stackoverflow.com/questions/5240789/scanf-leaves-the-new-line-char-in-the-buffer) – anastaciu Apr 05 '20 at 14:14
0

This code does what you are expected to do. I simplified the signature of the function get_string (not sure if the signature you provided was required or not). To the function we pass the array paragraphs (for proof of concept I am using an array with 300 positions, however if you should use malloc and realloc to adjust the size as needed) and the number of strings read in the function.

NOTE: Updated code to count words per paragraph in array as requested by OP.

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

void get_string(char *paragraphs, int *n) {

    char aux[30], i = 0, parg_cur_length = 0;

    do{
        fgets(aux, sizeof(aux), stdin);

        if(aux[0] == '\n')
            break;

        for(i=0; i< strlen(aux); i++){
            paragraphs[parg_cur_length + i] = aux[i];
        }
        parg_cur_length += strlen(aux);

        paragraphs[parg_cur_length] = '\0';
        parg_cur_length++;
        (*n)++;
    }while(aux[0] != '\n');
}

int main()
{
    char paragraphs[300];
    char * iter_paragraphs = paragraphs;
    int n_times = 0, n_chars = 0;

    get_string(paragraphs, &n_times);

    // let's print what we have
    for(int i = 0; i< n_times; i++) {
        n_chars = printf("%s", iter_paragraphs);
        iter_paragraphs += n_chars+1;
    }

    // reset pointer
    iter_paragraphs = &paragraphs[0];

    // let's counts the words per paragraph
    int j = 0, word_cnt = 0;

    for(int i = 0; i< n_times; i++) {

        while(*(iter_paragraphs + j) != '\0') {
            if( *(iter_paragraphs + j) == ' ')
                word_cnt++;
            j++;
        }

        // assuming last word does not have space but \n instead
        n_chars = printf("paragraph %d has %d words\n", i+1, word_cnt+1); 

        word_cnt = 0;

        // move to next pos in array due to \0
        j++;
    }
}

Nevertheless, IMO a cleaner approach for this would be to use a matrix (char **) as user3121023 suggested.

CRM
  • 4,569
  • 4
  • 27
  • 33
  • It is really good ! But i need count words and lines in paragraphs .When i use my word_counter function it counts words only from 1st sring (sentence) – Fearless_Wolf Apr 05 '20 at 13:16
  • You can do that in the main function after invoking get_string() or after you get the string from the user inside get_string(). In either case, you just need to iterate through each string (ending in \0) and count the spaces in each of them. You know that after \0 a new string starts until you reach n strings. – CRM Apr 05 '20 at 13:27
  • in which form the strings are stored in paragraphs ? is it like paragraphs={(sring)\n(sring)\n} ? – Fearless_Wolf Apr 05 '20 at 13:41
  • It is like this, "string\n\0string\n\0string\n\0" – CRM Apr 05 '20 at 13:56
  • should i do iteration with for loop or whit while – Fearless_Wolf Apr 05 '20 at 14:28
  • I've updated the code in order to count the words per paragraph. I did this in the main function but you can move it to its own function if you will. – CRM Apr 05 '20 at 14:30
  • i want to go through each line and use my func like num_words=0 num_words += count_words(line1) num_words += count_words(line2 ,3, ...n) and then print num_words How can i do hat and how ? Thanks in advance – Fearless_Wolf Apr 05 '20 at 15:10
  • Basically you need to apply the same logic as the one I added in the new version of the code. So, you pass the array paragraphs to the function or the lines of the array (depending on the logic you want) and in the function you count the words using the for and while loop (the same way as in the code above). – CRM Apr 05 '20 at 16:39