Взятие строк в качестве двумерного массива символов - PullRequest
0 голосов
/ 29 июня 2018

Мне нужен такой код, чтобы я вводил несколько строк одну за другой (нажимая ввод) и отображал его. например;

Введите

abc
def

выход

abc    
def

также я хочу, чтобы этот ввод был в массиве, чтобы я мог выбрать любой символ

из массива всякий раз, когда я хочу. Например: s [1] [1] дает 'e'.

Я написал код для этой проблемы.

#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");
    }
}

Но для этого кода мой ввод / вывод выглядит так:

Input

ab
cd

выход

abcd
cd

Может кто-нибудь сказать, где я иду не так?

Ответы [ 4 ]

0 голосов
/ 29 июня 2018

вы работаете с двумерным массивом char:

char a[n][m];

, но имейте в виду, что значение для 2-го индекса должно быть на 1 символ больше длины строки, которую вы хотите, чтобы в нем было место для байта \0. (все строки C должны заканчиваться нулем)

Это означает, что char a[n][m]; может содержать до n строк, каждая из которых имеет максимальную длину m-1 байтов.

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

Другая распространенная проблема при чтении пользовательского ввода в цикле - сбой при удалении любых нежелательных новых строк, которые могут привести к плохому поведению цикла. Ниже приведен пример того, как прочитать указанное пользователем число строк (используя fgets() вместо scanf()), каждая из которых имеет указанную пользователем длину: (также удаляя нежелательные символы новой строки (\n) в процессе)

Для удобства чтения следующий пример заменяет n & m на 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;
}
0 голосов
/ 29 июня 2018

Вы не указали значение ввода n и m в вопросе. Но из показанной входной и выходной строки кажется, что char array a[i] не имеет достаточно места для завершения нулевого символа \0. Когда вы задаете спецификатор формата %s, scanf() автоматически добавляет завершающий нулевой символ в конце сохраненной последовательности. Я попробовал ваш код с вводом 2 для n и m, и я получаю вывод, когда вы получаете:

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

Дайте значение 4 m, и вы получите:

2 4
ab
cd
ab
cd

При использовании scanf() для строкового ввода рекомендуется добавить проверку на максимальный модификатор символов, который на 1 меньше длины входного буфера. Итак, если размер входного буфера равен 4, то вы можете сделать

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

При этом scanf() будет читать не более 3 символов в a[i] и добавит \0 в четвертом месте a[i]. Остерегайтесь этого, он не отбрасывает оставшиеся входные данные из входного потока, и они будут использованы последовательным вызовом scanf().

Если вы хотите отбросить дополнительный ввод, который не использовался scanf, один из способов сделать это - прочитать и отбросить дополнительный ввод, используя цикл, например:

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

Вы можете добавить его после scanf() чтения данных из входного потока, например:

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

Это будет хорошо работать для ввода, который не содержит пробельных символов. Если ваш ввод содержит какой-либо символ пробела, он может работать не так, как ожидалось. Следовательно, я бы посоветовал вам прочитать о fgets(), который дает вам лучший контроль над вводом строки.

Проверьте это: fgets
и это: Как читать из stdin с помощью fgets ()?

0 голосов
/ 29 июня 2018

Попробуйте использовать fgets для захвата ввода. В этом случае трудно ограничить scanf количеством символов, разрешенным m. fgets позаботится об этом, но помните, что символ новой строки - это один из символов, подсчитанных как 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]);
    }
}
0 голосов
/ 29 июня 2018

Все строки в C должны заканчиваться нулевым символом \0, print знает об этом и печатает все символы ДО этого знака. Чтобы избежать этой проблемы, вы должны сделать все свои строки на 1 символ длиннее, чем слова, которые вы планируете вписать в них, и заполнить их 0 (0 - целое значение \0) в начале.

...