C многомерный массив указанием проблемы? - PullRequest
0 голосов
/ 08 октября 2018

Попытка взять строки в качестве входных данных и поместить их в 2d массив.Почему этот код показывает другое поведение?Последний цикл for "arr [i] [j]" не печатает строку. Он также даже не печатает символ.

Почему этот код не работает. Только этот код.новый способ записи

Этот код принимает ввод просто отлично (или, по крайней мере, так, как нужно. каждая строка не содержит ни одного пробела). И когда короткая строка сохраняется, оставшиеся заполнены нулем послевозврат каретки.Когда arr [] передается в последнем цикле for, все кажется нормальным, только когда передается arr [] [], возникает проблема. Но снова arr [] [] инициализируется как arr [1] [0], а затем arr [2][0] так не должно работать!

#include <stdio.h>
#include <stdbool.h>

int main(void){
    int i,j,m;
    scanf("%d",&m);
    char arr[m][50];
   for(i=0;i<m;i++){
       for(j=0;j<50;j++){   
    printf("please enter a string");
    scanf("%s",&arr[i][j]);
/*j is always 0. arr[i] takes string without space and store ending with null*/
    break;
       }

    }
  //Everything fine upto this,including storing a small continuous string in arr[i](where i<50) and null terminating*/
    for(i=0;i<m;i++){
        for(j=0;j<50;j++){
        printf("%s\n",arr[i][j]);
        break;
    }

}
    }

Ответы [ 3 ]

0 голосов
/ 08 октября 2018

У вашей программы есть несколько проблем, например, использование неправильного спецификатора формата:

scanf("%s",&arr[i][j]);

arr[i][j] - это символ, и вы используете %s спецификатор формата.Если вы хотите, чтобы ваша программа принимала строку в качестве входных данных, вам просто нужно сделать:

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

Поскольку вы задали размер 50 символов, установите в scanf() ограничение, чтобы не читать большечем 49 символов (оставшееся одно символьное пространство для нулевого завершающего символа), например:

scanf("%49s",arr[i]);
        ^^

Осторожно с этим, он не сбрасывает оставшийся ввод из входного потока, когда входные символы больше 49 и оставшиеся символы будут использованы последующим вызовом scanf().

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

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

В случае, если у вас есть какие-либо сомнения по поводу , как это отбросит дополнительный ввод , я бы предложил сначала пройти GetChar () .

Собрав все это вместе, вы можете сделать:

#include <stdio.h>

int main(void){
    int i,m;
    scanf("%d",&m);
    char arr[m][50];

    for(i=0;i<m;i++){
        printf("please enter a string");
        scanf("%49s",arr[i]);
        int c;
        while((c = getchar()) != '\n' && c != EOF)  // <=== This loop read the extra input characters and discard them
            /* discard the character */;
    }

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

РЕДАКТИРОВАТЬ

Ниже редактируется, потому что OP обновил вопрос и добавил- Почему этот код не работает. Только этот код. Не новый способ его записи

Выше в своем ответе я уже говорил, что вы используете неверный спецификатор формата в scanf().В этой части вашего кода:

for(i=0;i<m;i++){
   for(j=0;j<50;j++){   // <====== Nested for loop
printf("please enter a string");
scanf("%s",&arr[i][j]);  
// since the nested loop is supposed to run 50 times, assuming you are trying to read character by character and using %s format specifier
break;
// the nested loop will break in the first iteration itself unconditionally, do you really need nested loop here!
   }

}

Проверьте встроенные комментарии.Надеюсь, что это может дать представление об ошибках, которые вы делаете.

Кажется, что вы хотите читать символьную строку, используя scanf().Если дело обстоит именно так, убедитесь, что позаботились о нулевом завершающем символе, потому что в C строки на самом деле являются одномерным массивом символов, оканчивающимся нулевым символом '\0'.
Вы можете сделать:

#include <stdio.h>

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

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

    printf ("Enter number of strings: ");
    scanf("%d",&m);
    discard_extra_input();

    char arr[m][50];
    for(i=0;i<m;i++){
        printf("please enter string number %d: ", i+1);
        for(j=0;j<49;j++){
            scanf("%c",&arr[i][j]);
            if (arr[i][j] == '\n') {
                //need to add null terminating character manually
                arr[i][j] = '\0';
                break;
            }
        }
        if (j==49) {
            // In case where the input from user is more than 50 characters,
            // need to add null terminating character manually.
            arr[i][j] = '\0';

            // discard the extra input when input from user is more than 50 characters.
            discard_extra_input();
        }
    }

    for(i=0;i<m;i++){
        for(j=0;j<50 && arr[i][j]!='\0';j++){
            printf("%c",arr[i][j]);
        }
        printf ("\n");
    }
    return 0;
}

Код не требует пояснений, за исключением одного - вызов функции discard_extra_input() после первого ввода от пользователя scanf("%d",&m);.Причина -
Посмотрите на оператор:

scanf("%c",&arr[i][j]);

спецификатор формата %c будет использовать оставшийся символ новой строки '\n' из потока ввода из-за нажатия клавиши ENTER после первого вводапользователь (количество строк, введенных пользователем) .Следовательно, чтобы его отменить, вызывается функция discard_extra_input().В другом месте он использовался для отбрасывания символов, когда пользователь вводил строку размером более 49.

Надеюсь, это поможет.

0 голосов
/ 08 октября 2018

Я знаю код.Но ищу конкретные ответы.Где проблема заключается в коде

Проблема здесь:

  scanf("%s",&arr[i][j]);

и здесь:

printf("%s", arr[i][j]);

Это конкретный ответ, который вы ищетеfor.

%s не выполняет никакой связанной проверки.Он добавляет символы, начиная с ячейки памяти arr + i * m + j до arr + i * m + j + (length of input) + 1 (один дополнительный символ для дополнительного нулевого символа, который добавляет scanf).Взять пример ввода.Предположим произвольный начальный адрес для arr и выполним вычисления.Также учитывайте любые записи за пределами выделенного пространства для arr приводит к неопределенное поведение .

Аналогичным образом printf("%s", arr[i][j]); будет пытаться начать чтение с адреса arr [i] [j] , пока не найдет нулевой символ.Обычно это приводит к сбою кода, потому что если в вашей строке есть символы ascii, адрес будет слишком низким, чтобы указывать на любую действительную отображаемую пользователем память.Если ваш код работает, это в основном потому, что у вас уже есть UB в вашем scanf.

Возьмите ручку и бумагу и выполните несколько пробных прогонов

0 голосов
/ 08 октября 2018

Это довольно простая проблема, приятель.На самом деле вы правильно поняли, что вам нужно использовать 2d массив для хранения строк.Просто использование немного неправильное.

Прежде всего позвольте мне рассказать вам, как нужно использовать 2d массивы для хранения в c.В вашем двумерном массиве есть строки и столбцы.Скажем, строка представлена ​​i, а столбцы - j, т. Е. Каждая строка arr[i] содержит j элементов.Таким образом, в вашем контексте каждая строка arr[i] содержит каждую строку длиной до 50 символов.Так что scanf должно быть только для arr[i].И вам нужно выполнить цикл for, m раз, чтобы принять m строки.

То же самое относится и к печати. ​​

Вот рабочий код:

#include <stdio.h>
#include <stdbool.h>

int main(void){
    int i,j,m;
    printf("\nenter m value:");
    scanf("%d",&m);
    char arr[m][50];
   for(i=0;i<m;i++){ 
    printf("\nplease enter a string no %d: ", (i+1));
    scanf("%s",arr[i]);
    }
    printf("\nthe strings are: \n");
    for(i=0;i<m;i++){
      printf("\n%s\n",arr[i]);
    }
}

И вывод на случай, если вы хотите провести перекрестную проверку:

ВЫХОД:

введите значение m: 3

введите строку № 1: qwerty

пожалуйста, введите строку № 2: asdfgh

пожалуйста, введите строку № 3: zxcvbn

строки:

qwerty

asdfgh

zxcvbn

...