1 Востаннє редагувалося Lata (14.12.2020 21:49:19)

Тема: Вказівники мовою С

Добрий вечір!
Є питання.
Умова задачі. Дано одновимірний масив С, який складається з 12 елементів. Вилучити з масиву k-й елемент масиву (k<12).
Задача легка, якщо її робити без вказівників ;) , але треба з вказівниками ]:->

#include <stdio.h>
int main ()
{
  float C[12] = {2.1,0.4,0.1,-0.5,0.6,7.1,-2.4,-1.3,-0.7,-9,0,1.2}, B[11];
  int k;
  printf ("Вектор С\n");
  for(int i=0;i<12;i++){
    printf("%.1f\t",C[i]);
  }
  printf ("\nУведіть номер елемента, який необхідно вилучити, k=\t");
  scanf("%i",&k);
  if((k<0)||(k>12)){
    printf ("Уведіть інше значення\t"); 
  } 
  else{
    for(int i=0;i<12;i++){
        if(i!=k){
        *(B+i)=*(C+i);
        }
    }
    for(int i=0;i<11;i++){
        printf("%.1f\t",B[i]);
    }
  }
  return 0;

Якщо ввести значення к, що задовільняє умову, то все одно буде функція scanf, яка буде ставити нові поля і зчитувати значення %)
Що робити? Дякую всім наперед!

2

Re: Вказівники мовою С

if(i=!k){

-->

if(i != k){

Яка умова перевіряється в if(i=!k) на вашу думку?

Подякували: Lata1

3

Re: Вказівники мовою С

Ну, тут перевіряється, чи i(порядковий номер) не дорівнює номеру того елемента, якого треба вилучити.
Не зовсім розумію Вас, Arete. Потрібно придумати іншу умову?

4

Re: Вказівники мовою С

if(i = !k)

Ви присвоюєте змінній "i" значення "не k", а потім результат присвоєння перевіряєте в виразі if.

1. Якщо k == 0, то "не k" буде true, інакше false.
2. Потім цей "не k" (true чи false) конвертується в число (можливо в 1 чи 0, залежно від true чи false) і це число присвоюється змінній "i".
3. Потім в виразі if змінна "i" знову конвертується в булевий тип і перевіряється на істинність.

В C++ вираз "не дорівнює" позначається як !=, а не як =! .

Подякували: Lata, koala, leofun013

5 Востаннє редагувалося Lata (14.12.2020 21:48:29)

Re: Вказівники мовою С

В С також) *THUMBSUP*
Дякую, Arete! :-*  І чого я така неуважна? :[
Тепер залишається подумати, як зробити так, щоб елемент з індексом к просто зник, а не став нулем *KISSING*
Це взагалі можливо? Не можу зрозуміти)

6

Re: Вказівники мовою С

То як це зробити?
Я хочу, щоб елемент k просто зник, а не відображався як 0.00. Вчора довго думала, але щось не виходило.

7

Re: Вказівники мовою С

Такої операції, як видалення з масиву, в C/C++ немає.  Треба перемістити решту елементів. Десь так:

Індекс 0 1 2 3 4 5
 Було: 5 7 3 2 8 1
       | | |  / /
Стало: 5 7 3 8 1 _

Останній елемент (_), якщо він є, при цьому ігнорується; а якщо ви не просто видаляєте, а копіюєте в інший масив усе, крім потрібного елемента, то можна його і не робити взагалі. Головне - скопіювати елементи після "видаленого" зі зсувом.

Подякували: Lata1

8 Востаннє редагувалося tchort (15.12.2020 11:14:09)

Re: Вказівники мовою С

Треба перемістити решту елементів. ... Головне - скопіювати елементи після "видаленого" зі зсувом.

Заждіть, але в умові нічого не було про збереження порядку. Навіщо щось штовхати туди-сюди? Чому просто не перезаписати елемент який потрібно видалити, тим що на кінці? А останній ігнорувати чи обнулити. (*Зазначте я не експерт в С.)

Подякували: Lata1

9

Re: Вказівники мовою С

Тут є суміш двох рівнів абстракції. Є абстрактний об'єкт - набір елементів; і є структура даних, що його представляє. Абстрактний масив є набором послідовно пронумерованих елементів, але з нього видалити щось неможливо (хіба що з кінця). Логічно вважати, що при змінах масиву необхідно зберігати послідовність, бо це властивість масиву. Але якщо ми маємо абстрактну множину, представлену масивом як структурою даних, то таке видалення цілком коректне.

І так, пам'ять - це величезний масив, а вказівники - індекси в ньому. Може, так буде зрозуміліше.

Подякували: Lata1

10

Re: Вказівники мовою С

Спробувала провести зсув, але все рівно видає 0.00. Що знов не так?

#include <stdio.h>
int main ()
{
  float C[12] = {2.1,0.4,0.1,-0.5,0.6,7.1,-2.4,-1.3,-0.7,-9,0,1.2}, B[11];
  int k;
  printf ("Вектор С\n");
  for(int i=0;i<12;i++){
    printf("%.1f\t",C[i]);
  }
  printf ("\nУведіть номер елемента, який необхідно вилучити, k=\t");
  scanf("%i",&k);
  if((k<0)||(k>12))
    printf ("Уведіть інше значення\t"); 
  else{
    for(int i=0;i<12;i++){
        if((i!=k)&&(i<k)){
        *(B+i)=*(C+i);
        }
        if(i>k){
         *(B+i)=*(C+i+1);   
        }
    }
    for(int i=0;i<11;i++){
        printf("%.1f\t",B[i]);
    }
  }
  return 0;
}

11

Re: Вказівники мовою С

Взагалі це не зовсім вказівники. Тобто так, формально ви тут використовуєте арифметику вказівників, але *(B+i) - це синонім B[i]. Тобто ви користуєтеся вказівниками точно так, як індексами.
Проблема в тому, що при i==k ви взагалі не копіюєте нічого. В результаті B[k] лишається неініціалізованим - у вашому випадку, випадково нулем. Якщо по-вашому, то треба робити

if(i<k) 
  *(B+i)=*(C+i);
else //так, і при i==k
  *(B+i)=*(C+i+1);

А якщо по-хорошому з вказівниками, то

#include <stdio.h>

#define SIZE 12
#define NEW_SIZE (SIZE-1)

int main ()
{
  float c[SIZE] = {2.1,0.4,0.1,-0.5,0.6,7.1,-2.4,-1.3,-0.7,-9,0,1.2}, 
        b[NEW_SIZE];
  printf ("Вектор С\n");
  for(float *i=c; i<c+SIZE; i++){
    printf("%.1f\t",*i);
  }
  int k;
  printf ("\nУведіть номер елемента, який необхідно вилучити, k=\t");
  scanf("%i",&k);
  if((k<0)||(SIZE<=k))//тут >=, k==SIZE нам не підходить
    printf ("Уведіть інше значення\t"); 
  else{
      float *to_remove = c+k;
      for(float *i=c, *j=b; i<c+SIZE && j<b+NEW_SIZE;++i,++j) {
        if(i==to_remove) {
            i++;
        }
        *j=*i;
    }
    for(float *i=b; i<b+NEW_SIZE; i++){
      printf("%.1f\t",*i);
    }
  }
  return 0;
}
Подякували: Lata, Arete2

12

Re: Вказівники мовою С

Я напишу по-своєму. Так якось зрозуміліше)
Ось весь працюючий код. Залишаю для наступних поколінь студентів-першокурсників)

#include <stdio.h>
int main ()
{
  float C[12] = {2.1,0.4,0.1,-0.5,0.6,7.1,-2.4,-1.3,-0.7,-9,0,1.2}, B[11];
  int k;
  printf ("Вектор С\n");
  for(int i=0;i<12;i++){
    printf("%.1f\t",C[i]);
  }
  printf ("\nУведіть номер елемента, який необхідно вилучити, k=\t");
  scanf("%i",&k);
  if((k<0)||(k>12))
    printf ("Уведіть інше значення\t"); 
  else{
    for(int i=0;i<12;i++){
        if(i<k){
        *(B+i)=*(C+i);
        }
        else{
         *(B+i)=*(C+i+1);   
        }
    }
    for(int i=0;i<11;i++){
        printf("%.1f\t",B[i]);
    }
  }
  return 0;
}

Дякую всім за допомогу *THUMBSUP* ! І, як завжди, особливо дякую Коалі *ROSE*

Подякували: Arete1

13

Re: Вказівники мовою С

Хоча і Коалин код можна зрозуміти. Я вже все зрозуміла, здається *YAHOO*