0

The output of code
I want to create an array of character in which there are 'n' rows and each row have a character. In the given code I asked the user to enter the number of rows(n) then I create a variable 'chr' and each row contain only one character. Then I asked the characters one by one and store them in their respective rows but when I take the print of those characters something strange happens. The first row which should only store one character of its own stores all the characters of different rows. Why? can anyone explain to me this?

#include <stdio.h>

int main(void) {
    int n;
    scanf("%d", &n);

    char chr[n][1];

    for (int i = 0; i < n; i++) {
        printf("Enter the %d character?\n", i);
        scanf("%s", chr[i]);
    }
    // printing
    for (int i = 0; i < n; i++) {
        printf("\n%s\n", chr[i]);
    }
    return 0;
}
  • 1
    you only are allocating one byte of memory for each row. – OldProgrammer Feb 15 '20 at 15:36
  • 2
    Because you have not terminated each "line" with a null termination byte it will print until it finds a null character. – fredrik Feb 15 '20 at 15:37
  • @OldProgrammer Because I only want a character to be taken from each row. – Ankit Jangid Feb 15 '20 at 15:39
  • @fredrik It´s not even only about printing. Each dimension can store only one character and `scanf` writes the terminating `/0` for each string in the first and only object of the next row. This routine gets iterated over and over again and after all, the memory is just a big mess of "sliced" strings, plus the last `/0` is written beyond the bounds of the array. That is a complete pack of Undefined Behavior before it even gets to the printing part of the program. – RobertS supports Monica Cellio Feb 15 '20 at 17:49

2 Answers2

3

The first row which should only store one character of its own stores all the characters of different rows. Why? can anyone explain to me this?

scanf("%s", chr[i]);

%s reads a whole string until it encounters a white space character, such as newline \n, and writes it (excluding the white space character) into the first dimension; not only one character.

You also forgot that since you are trying to read a string a \0 is automatically appended to each string, but since the declaration of chr there is just place for one character in a dimension, not two.

A multi-dimensional array is allocated continously in memory, which provides the effect that the \0 character for the string in the previous dimension is stored at the first and only character of the next dimension; in the next iteration scanf overwrites then this \0 character to store the second character but again writes the \0 of this string into the first an only object of the following dimension and goes so on and on for each iteration, which ends up in a complete mess of Undefined Behavior, plus the \0 of the last string is written beyond the bounds of the complete multi-dimensional array.

So you can´t even say that they were stored in just one dimension, which isn´t the case, even if it seems like it would.

For more information about Undefined Behavior look at this question:

Undefined, unspecified and implementation-defined behavior


Rather use

scanf(" %c", &chr[i][0]);

with the %c format specifier to read only one character per iteration and implement a white space character before the %cformat specifier to catch the newline \n left in stdin by the scanf consumption of the previous loop walkthrough or any leading white space.


Also, change:

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

to

  for(int i = 0; i<n; i++) {
    printf("\n %c \n", chr[i][0]);

The whole code shall then be:

#include <stdio.h>

int main(void) {

  int n;
  scanf("%d", &n);

  char chr[n][1];

  for(int i = 0; i<n; i++) {
    printf("Enter the %d character?\n", i);
    scanf(" %c", &chr[i][0]);
  }
  // printing
  for(int i = 0; i<n; i++) {
    printf("\n %c \n", chr[i][0]);
  }
return 0;
}
0

as to answer why its printing the other caracters, they are directly behind each other in memory, and as others pointed out since you told it to print a string, it treats those chars in a row as one string (which is an array of chars) until it encounters a termination char.

so in memory this

char array[3][1] = {{'a'},{'b'}{'c'}};

looks just like this:

char array[3] ={'a','b','c'};

or this

char array[3] = {"abc"};

the array variable is a pointer to the address in memory where the first char is positioned, if you use [] you just jump sizeof(char) amount of bytes to the next char,

with the 2D array this is similar, the 1st bracket makes you jump sizeof(2darray[0]) bytes, which is in this case the same as sizeof(char) since length is 1

NasaOK
  • 81
  • 5