1

I want to receive the number of lines of input from the user then read and save the lines of unknown lengths in an array.

I know that the way I am saving the lines is wrong but I don't know how to correct it.

int nos; // number of strings
scanf_s("%d", &nos);
char** strs = malloc(nos * sizeof(char*)); // array of strings
for (int i = 0; i < nos; i++) // receiving strings
{
    scanf_s("%s", (strs+i));
}
S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
Pegi
  • 147
  • 8
  • 2
    Possible duplicate of [How can I read an input string of unknown length?](https://stackoverflow.com/questions/16870485/how-can-i-read-an-input-string-of-unknown-length) – Eugene Sh. May 03 '19 at 16:50
  • my problem is not only with reading one string but also saving multiple lines in an array – Pegi May 03 '19 at 16:55
  • You're only allocating space for your pointer of pointers. But not for your actual strings. – Gabriel Pellegrino May 03 '19 at 16:55
  • You can use the `%ms` format string in POSIX-compliant systems for that. – S.S. Anne May 03 '19 at 16:56
  • On a POSIX system (like Linux or macOS) I recommend [`getline`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getdelim.html). – Some programmer dude May 03 '19 at 17:02
  • If you want something more portable, perhaps using small buffers and multiple calls to [`fgets`](https://en.cppreference.com/w/c/io/fgets) until you have read the full line ([reallocating](https://en.cppreference.com/w/c/memory/realloc) as needed). Do this in a loop until all off the lines have been read. – Some programmer dude May 03 '19 at 17:04
  • You are not clear, do you want to read a line may be containing separators (space / tag) or to read a word ? Your title says line but your implementation says word – bruno May 03 '19 at 17:21
  • "I want to receive the number of lines of input from the user then read and save the lines". No, you don't. Or, rather, your main problem is your desire to know up front how many lines you'll be getting. Just read the data. If you get a line that is longer than your current buffer can handle, reallocate and make it bigger. If the number of lines you receive is larger than the amount of space you currently have to store them, reallocate and increase your available space. – William Pursell May 03 '19 at 17:22
  • @bruno lines including separators – Pegi May 03 '19 at 17:59
  • @Pegi so you cannot use _scanf_ or an equivalent – bruno May 03 '19 at 18:00

2 Answers2

1

You're close, but you're forgetting to allocate memory for the string. If you're working with POSIX-compliant systems (i.e. pretty much everything except Windows) then use the %ms scanf() format specifier to allocate the buffer for the string as you're reading it (note that this stops after whitespace):

scanf("%ms", &strs[i]);

For Windows, implement a gets()-like function:

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

int msgets(char **str)
{
    int ch = 0;
    size_t len = 0;

    while(ch != '\n')
    {
        len++;
        *str = realloc(*str, len);
        ch = getchar();
        (*str)[len-1] = ch;
    }
    (*str)[--len] = 0;
    return len;
}

Here's how to use it in replacement of the scanf() line:

msgets(&strs[i]);

Other than that, your code looks fine.

Here's an almost complete example with my code included:

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

int msgets(char **str)
{
    int ch = 0;
    size_t len = 0;

    while(ch != '\n')
    {
        len++;
        *str = realloc(*str, len);
        ch = getchar();
        (*str)[len-1] = ch;
    }
    (*str)[--len] = 0;
    return len;
}

int main(void)
{
    int nos; // number of strings
    scanf("%d ", &nos);
    char** strs = malloc(nos * sizeof(char*)); // array of strings
    for (int i = 0; i < nos; i++) // receiving strings
    {
        msgets(&strs[i]);
    }
    /* Do something with strs[] here */
    return 0;
}
S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
-1

if you read carefully this answerHow can I read an input string of unknown length? , and modify your code it should be something like this. I also add a print for loop to see the results of this code

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

char *inputString(FILE* fp, size_t size){
    char *str=NULL;
    int ch;
    size_t len = 0;
    str = realloc(str, sizeof(char)*size);
    if(!str){
      printf("[DEBUG]\n");
      return str;
    }
    while(EOF!=(ch=fgetc(fp)) && ch != '\n'){
        str[len++]=ch;
        if(len==size){
            str = realloc(str, sizeof(char)*(size+=16));
            if(!str)return str;
        }
    }
    str[len++]='\0';

    return realloc(str, sizeof(char)*len);
}


void empty_stdin (void) /* simple helper-function to empty stdin */
{
    char c;
    while ((c = getchar()) != '\n' && c != EOF);
    return;
}


int main(void){
  int nos,i; /*number of strings*/
  scanf("%d", &nos);
  empty_stdin();
  char ** strs = malloc(nos * sizeof(char*)); /*array of strings*/
  for (i = 0; i < nos; i++) {/*receiving strings*/
      *(strs+i) = inputString(stdin,1);
  }
  for(i=0;i<nos;i++){
    printf("%s\n",*(strs+i));
  }
  return 0;
}

input:

3
123456789
foo
hello world

output:

123456789
foo
hello world