0

I want a code such that I enter some strings one-by-one (by pressing enter) and display it. for example;

Input

abc
def

Output

abc    
def

also I want this input to be in a array so that I can select any character

from the array whenever I want. For example: s[1][1] gives 'e'.

I have writen a code for this problem.

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

int main()
{
    int i, j, n, m;

    scanf("%d%d", &n, &m);
    char a[n][m];

    for (i = 0; i<n; i++)
        scanf("%s", a[i]);


    for (i = 0; i<n; i++) {
        printf("%s", a[i]);
        printf("\n");
    }
}

But for this code my input/output goes like this:

Input

ab
cd

Output

abcd
cd

Can anyone tell where am I going wrong?

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • The input you have shown in question is missing the input value of `n` and `m`. Show the input value you are giving to `n` and `m`. – H.S. Jun 29 '18 at 11:05
  • While with gcc and `c99+` there is no problem with the *Variable Length Array of Arrays* `char a[n][m];`, note that not all compilers support them. After you have the basics handled, look at declaring/allocating a number of pointers (e.g. `char **a = malloc (n * sizeof *a);`), reading with a sufficiently large buffer (e.g. `char buf[1024] = ""; scanf("%s", buf);` (checking return)) and then allocating storage for each string (e.g. `a[0] = malloc (strlen (buf) + 1); strcpy (a[0], buf);`). This provides allocated storage for your strings, while providing access with string indexes, `a[1][1]`, – David C. Rankin Jun 29 '18 at 18:56

3 Answers3

1

You have not shown the input value of n and m in the question. But from the input and output string shown, it seems that char array a[i] does not have the enough space for terminating null-character \0. When you give format specifier %s, scanf() automatically adds a terminating null character at the end of the stored sequence. I tried your code with input 2 for both n and m and I am getting the output as you are getting:

$ ./a.out
2 2
ab
cd
abcd
cd

Give the value 4 to m and the output is:

2 4
ab
cd
ab
cd

When using scanf() for string input, it is good to add check for max character modifier that is 1 less than the length of the input buffer. So, if the size of input buffer is 4 then you can do

scanf("%3s",a[i]);

With this, the scanf() will read not more than 3 characters in a[i] and will add \0 at the fourth location of a[i]. Beware with this, it does not discard the remaining input from input stream and they will be consumed by consecutive scanf() call.

If you want to drop the extra input which wasn't consumed by scanf, one way of doing it is to read and discard the extra input using a loop, like this:

int c;
while((c = getchar()) != '\n' && c != EOF)
    /* discard the character */;

You can add it after scanf() reads data from input stream, like this:

    for(i=0; i<n; i++) {
        scanf("%3s", a[i]);  // assuming the size of a[i] is 4
        int c;
        while((c = getchar()) != '\n' && c != EOF)  // <=== This loop read the extra input characters and discard them
            /* discard the character */;
    }

This will work fine for the input that does not contain any whitespace characters. If your input contain any whitespace character, it may not behave as expected. Hence, I would suggest you to read about fgets() which gives you better control for string input.

Check this: fgets
and this: How to read from stdin with fgets()?

H.S.
  • 11,654
  • 2
  • 15
  • 32
0

All strings in C must be terminated with the null character \0, print knows this and prints all character UP TO that sign. You should make all of your strings 1 character longer than the words you plan to fit in them and fill them with 0 (0 is the integer value of \0) in the start to avoid this problem.

Qubit
  • 1,175
  • 9
  • 18
0

you are working with a 2D array of char:

char a[n][m];

but keep in mind the value for the 2nd index should be 1 character longer than the length of the string you wish it to allow room for the \0 byte. (all C strings must be null terminated)

This means char a[n][m]; can contain up to n strings, each string with maximum length of m-1 bytes.

char exampleStr[] = {"char count"}; //for example contains 11 characters (not 10)

|c|h|a|r| |c|o|u|n|t|\0|  //note nul char is appended

Another common problem when reading user input in a loop is failure to remove any unwanted newlines, which can cause the loop to behave poorly. Following is an example of how to read a user specified number of strings ( using fgets() instead of scanf() ), each with a user specified length: (also removing unwanted newlines ( \n ) in the process)

For readability, the following example replaces n & m with lines & maxLen.

int main(void)
{
    int lines, maxLen, i=0;

    printf("Enter number of lines:");
    scanf(" %d", &lines);
    printf("Enter maxLen line length:");
    scanf(" %d", &maxLen);

    char line[lines][maxLen+2]; //+2 to allow for trailing newline and null

    fgets(line[i], maxLen, stdin);//consume anything left in stdout
    printf("Enter up to %d characters and hit return:\n%d) ", maxLen, i+1);
    for(i=0;i<(lines);i++)
    {
        fgets(line[i], maxLen, stdin);
        line[i][strcspn(line[i], "\n")] = 0; // clear newline
        printf("Enter up to %d characters and hit return:\n%d) ", maxLen, i+1);
    }

    return 0;
}
ryyker
  • 22,849
  • 3
  • 43
  • 87
  • The extra `line[i][strcspn(line[i], "\n")] = 0` is useless as the `%s` conversion format reads words, not lines. It would be useful if you were reading lines with `fgets()` (a safer approach indeed) but you would need to define line as `char line[lines][maxLen+2];` to allow for both the trailing newline and the null terminator. – chqrlie Jun 29 '18 at 15:56
  • @chqrlie - Good feedback. Edited suggestions in. – ryyker Jul 02 '18 at 12:34