0

Practice.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define ARR 32

int main(void){

  int MEM=64;
  char arr[ARR],*p=(char *)calloc(MEM,(sizeof(char))),*q=NULL;
  int i=0,j=1;

  printf("\nEnter String : ");

  while(j){

    scanf(" %[^\n]s " ,arr);

    if(j==1)
      strcpy(p,arr);
    else
      strcat(p,arr);


    if((j*ARR)==MEM){
      MEM=MEM+(j*ARR);
      q=realloc(p, MEM);
      if(!(q)){
        printf("\nNOT ENOUGH MEMORY\n");
        goto END;
      }
      p=q;
    }


    for(i=0;i<(strlen(arr));++i){
      if(arr[i]=='\n')
        break;
    }


    if(arr[i]=='\n')
      break;


    ++j;
  }

  printf("\n %s\n",p);


  END: free(p);p=NULL;q=NULL;

  return 0;
}

I am trying to get multiple string inputs.

I am using scanf(" %[^\n]s",arr); to take the input instead of fgets(arr,ARR,stdin);, because with fgets the program execution stops as soon as I hit ENTER key. But with scanf(" %[^\n]s",arr); the program is unable to get out of the while() loop even after entering \n.

I would like to know the mistake or mistakes I have made while writing the code.

phougatv
  • 881
  • 2
  • 12
  • 29

2 Answers2

2

The canonical way of reading multiple lines of input in C is to use fgets in a loop, like

while (fgets(arr, sizeof(arr), stdin) != NULL)
{
    if (arr_contains_special_input_to_exit_loop(arr))
        break;

    // Optionally check for and remove trailing newline from input

    // Append `arr` to your data
}

The condition to exit the loop might be some special input or an empty line or something else completely.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

One mistake is:

for(i=0;i<(strlen(arr));++i){
  if(arr[i]=='\n')
    break;
}

Looking earlier in you code you have:

scanf(" %[^\n]s " ,arr);

The [^\n] prevents any newlines \n from being contained in arr. So your loop that looks for (arr[i]=='\n') will never find any. Your next bit of code continues looking for non-existent newlines:

if(arr[i]=='\n')
  break;

This last break also breaks out of your outer loop preventing you from asking for further input on finding a newline (which it shouldn't). Fix these issues and it should get much further allowing you to enter multiple items.


Edit:

With a bit of effort looking at what you were doing, I now have it taking multiple input and reallocating as necessary. The strings are all concatenated and printed at the end. It could still stand a bit of work, but this should give you a few hints:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define ARR 32

int main (void) {

    int MEM = 64;
    char arr[ARR], *p = (char *) calloc (MEM, (sizeof (char))), *q = NULL;
    int i = 0, j = 1;


    while (j) {

        printf ("\nEnter String : ");
        scanf (" %[^\n]s ", arr);
        printf (" you entered (arr): %s\n", arr);
        if (strcmp (arr, "q") == 0) {
            printf ("\n  'q' entered, exiting.\n\n"); // provide for exit if `q` entered
            break;
        }

        if (j == 1)
            strcpy (p, arr);
        else
            strcat (p, arr);

        if ((j * ARR) == MEM) {
            MEM = MEM + (j * ARR);
            q = realloc (p, MEM);
            if (!q) {
                printf ("\nNOT ENOUGH MEMORY\n");
                goto END;
            }
            else
                printf ("\nMemory Reallocation - succeeded.\n");
            p = q;
        }
        ++j;
    }

    printf (" %s\n", p);

END:
    if (p) free (p);  /* always test pointer before calling free */
    p = NULL;
    q = NULL;

    return 0;
}

output:

./bin/me

Enter String : fishinsea
  you entered (arr): fishinsea

Enter String : alligators
  you entered (arr): alligators

Memory Reallocation - succeeded.


Enter String : really_big_mosters
  you entered (arr): really_big_mosters

Enter String : SuperSnake_Prudhome
  you entered (arr): SuperSnake_Prudhome

Memory Reallocation - succeeded.

Enter String : 8_puppies
  you entered (arr): 8_puppies

Enter String : q
  you entered (arr): q

  'q' entered, exiting.

fishinseaalligatorsreally_big_mostersSuperSnake_Prudhome8_puppies
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • I replaced `scanf(" %[^\n]s",arr);` by `fgets(arr,ARR-1,stdin);` but still the program enters the infinite loop. How would you suggest to overcome that? – phougatv Sep 04 '14 at 05:41
  • 1
    You need to flush the input buffer that still contains the 'newline' after you hit return. declare a dummy `int c;`. The after fgets, simply add the line `do { c=getchar(); } while ((c != '\n') || (c == EOF));` – David C. Rankin Sep 04 '14 at 05:59
  • In this code : `for (i = 0; i < (strlen (arr)); ++i) { if (arr[i] == '\n') break; } if (arr[i] == '\n') break;` When we are not using `\n` as an escape character, why are we still using it in the `for loop` to check the condition? – phougatv Sep 04 '14 at 06:08
  • 1
    There is no need -- you can toss it, I just didn't want to throw it out and have you wonder why. I'll edit and drop it. – David C. Rankin Sep 04 '14 at 06:29
  • May be because you were trying to check that this was actually my(rookie) own code & I have not copied from some book or person. That's why. – phougatv Sep 04 '14 at 06:32
  • Hah! That's a good one. I'm an old professional engineer and an attorney -- not a teacher :) I don't care where the code comes from, my only concern is that you start to get comfortable with what you are doing and why you are doing it and for you to develop good habits along the way. Your prof can worry about the rest :) – David C. Rankin Sep 04 '14 at 06:36
  • Yes, I saw your profile & its pretty impressive. The code is entirely mine but I really appreciate your approach, the way you took my code, edited it and answered me. Its very easy to understand from your own codes. Is this the correct reason for your `why?`, isn't it? ;) – phougatv Sep 04 '14 at 06:41
  • 1
    It is the Socratic Method. Your reward for every correct answer is -- another question. Keep up the good work. – David C. Rankin Sep 04 '14 at 06:45