简体   繁体   中英

Taking strings as a 2-D char array

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?

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()?

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.

Consider using fgets to capture input. In this case it is difficult to restrict scanf to the number of characters allowed by m . fgets takes care of that but remember that the newline is one of the characters counted by fgets .

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

int main( void)
{
    int i = 0;
    size_t n = 0, m = 0;
    int scanned = 0;
    char values[100] = "";

    do {
        printf ( "enter two values as x y ( x > 0 and y > 2)\n");
        if ( fgets ( values, sizeof values, stdin)) {
            scanned = sscanf ( values, "%zu%zu", &n ,&m);
        }
        else {
            fprintf ( stderr, "problem fgets\n");
            return 0;
        }
    } while ( scanned != 2 || n < 1 || m < 3);

    char a[n][m + 2];//+2 for newline and '\0'

    i = 0;
    do {
        printf ( "enter string %zu\n", i + 1);
        if ( !fgets ( a[i], m + 2, stdin)) {
            fprintf ( stderr, "problem fgets\n");
            return 0;
        }
        if ( !strchr ( a[i], '\n')) {//string does not have newline
            printf ( "enter no more than %zu characters\n", m);
            while ( !strchr ( a[i], '\n')) {//call until newline is found to clear input
                if ( !fgets ( a[i], m + 2, stdin)) {
                    fprintf ( stderr, "\nfgets problem\n");
                    return 0;
                }
            }
        }
        else {
            i++;
        }
    } while ( i < n);

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

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM