Witam wszystkich!
Jest to mój pierwszy wpis na tym forum.
Moim zadaniem jest utworzenie tablicy dwuwymiarowej zawierającej dane studentów np. imię, nazwisko, numer indeksu i dalsza praca z tą tablicą. Już dość długi czas męczę się, żeby jakkolwiek zaimplementować taką tablicę i wyświetlić ją na ekranie konsoli w postaci kolumn i wierszy.
Czy ktoś byłby w stanie nakierować mnie jak taki twór ma powstać?
Z góry dziękuję za wszystkie odpowiedzi! Pozdrawiam
To jest program, który wypisuje mi po prostu liczby w postaci takiej tablicy i mogę odczytać wartość z konkretnej komórki. Chciałbym zrobić to samo na napisach.
Edytowałem. Powinno być ok.
Tak naprawdę, to chciałbym się przede wszystkim dowiedzieć jak zaimplementować wyrazy w tablicy, żebym później mógł je wyświetlić w postaci %s, a nie jako pojedyncze litery(%c).
HypheN napisał(a):
Edytowałem. Powinno być ok.
No nie bardzo. Miałeś kod wrzucić jako tekst, a nie obrazki.
Tak naprawdę, to chciałbym się przede wszystkim dowiedzieć jak zaimplementować wyrazy w tablicy, żebym później mógł je wyświetlić w postaci %s, a nie jako pojedyncze litery(%c).
Jeśli tablica znaków posiada znak '\0'
to można ją wypisać poprzez %s
:
#include <stdio.h>
#include <string.h>
int main()
{
char str[10];
str[0] = 'a';
str[1] = 'l';
str[2] = 'a';
str[3] = '\0';
printf("%s, %lu\n", str, strlen(str));
return 0;
}
Okej. Rozumiem, a jak to zapisać w tablicy dwuwymiarowej? W sensie chciałbym żeby:
#include <stdio.h>
#include <string.h>
int main()
{
char str[10][10];
str[0][0] = "napis";
printf("%s, %lu\n", str, strlen(str));
return 0;
}
Taki zapis nie przechodzi, ale chciałem pokazać o co mi chodzi.
#include <stdio.h>
#include <string.h>
int main()
{
char str[10][10];
str[0][0] = 'a';
str[0][1] = 'l';
str[0][2] = 'a';
str[0][3] = '\0';
printf("%s, %lu\n", str[0], strlen(str[0]));
strncpy(str[1], "ma kota i konia i psa i dziadka", 9);
printf("%s, %lu\n", str[1], strlen(str[1]));
return 0;
}
Nie wiem dlaczego nikt nie zapytał...
Te dwuwymiarowe tablice chcesz bo musisz (ktoś Ci kazał tak zrobić) czy po prostu nie masz innego pomysłu ?
struct Student {
char imie[10];
char nazwisko[10];
int indeks;
};
int main()
{
struct Student tab[10];
...
}
Muszę, w poleceniu mam zapisane, aby za pomocą tablic dwuwymiarowych stworzyć bazę studentów.
Stwórz tablicę dwuwymiarową składającą się z kilku rekordów mieszczącą w sobie dane dotyczące studentów(imię, nazwisko, rocznik..)
1.Pozwól użytkownikowi wybrać jeden dowolny element tablicy(wybór wiersza i kolumny) i wyświetlić go w terminalu
2.Zapisz tablicę do pliku tekstowego.
3.Odczytaj zapisany plik tekstowy i wyświetl zawartość tablicy w terminalu.
Masz wykorzystać tablice dwuwymiarowe do czegoś takiego? A jaka jest definicja tablicy jako struktury danych? Tablica przechowuje dane ale TEGO SAMEGO TYPU. Więc jeśli masz imię i nazwisko jako C-łańcuchy
ale index
jako pole np. int
to w jakiej chcesz to tablicy zachować?.
To znaczy żeby było jasne. Da się to zrobić ale jako że przechowujesz różne dane musiałbyś mieć coś takiego: void*** studenci;
.
studenci = malloc(ile * (void**));
ile
odczytasz za pomocą scanf
. Chyba, że będziesz używać co chwilę realloc
(wersja bardziej hardcore'owa) :P
Później w pętli:
studenci[i] = malloc(3 * sizeof(void*));
bo masz 3 pola: imie
, nazwisko
i index
.
Później odczytujesz imie
, nazwisko
i dajesz je do jakiegoś większego bufora by sprawdzić ile znaków zajmują. Oraz odczytujesz wartość index
. I dajesz.
studenci[i][0] = malloc(strlen(buffer.imie) + 1);
strcpy(studenci[i][0], buffer.imie);
strcpy
automatycznie przekopiuje znak \0
z bufora.
index
jako że jest typu int
przekopiujesz za pomocą memcpy
.
Nie wiem czy o to chodziło temu który zlecił Ci to zadanie. Do tego wystarczy jednowymiarowa tablica struktur. Kod poniżej.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student {
char imie[20];
char nazwisko[30];
int index;
} buffer;
int main() {
void*** studenci;
int ile;
printf("Ile studentow: ");
scanf("%d", &ile);
studenci = malloc(ile * sizeof(void**));
for(int i=0; i<ile; i++) {
printf("Imie: ");
scanf("%s", &buffer.imie);
printf("Nazwisko: ");
scanf("%s", &buffer.nazwisko);
printf("Index: ");
scanf("%d", &buffer.index);
studenci[i] = malloc(3 * sizeof(void*));
int imieLen = strlen(buffer.imie) + 1;
int nazwiskoLen = strlen(buffer.nazwisko) + 1;
studenci[i][0] = malloc(imieLen);
studenci[i][1] = malloc(nazwiskoLen);
studenci[i][2] = malloc(sizeof(int));
strcpy(studenci[i][0], buffer.imie);
strcpy(studenci[i][1], buffer.nazwisko);
memcpy(studenci[i][2], &buffer.index, sizeof(int));
}
for(int i=0; i<ile; i++) {
/* wypisze: 0: [Jan, Kowalski, 50] */
printf("%d: [%s, %s, %d]\n", i, (char*)studenci[i][0], (char*)studenci[i][1], *(int*)studenci[i][2]);
}
Aha to nie jest cały kod. Nie zapomnij zwolnić pamięci :P
Jedynie czego uczy to zadanie to posługiwanie się wskaźnikami do void
.
Paskudztwo... No to coś w tym stylu...
#define WIERSZE 10
#define KOLUMNY 3
#define IMIE 0
#define NAZWISKO 1
#define INDEKS 2
...
char * tab[WIERSZE][KOLUMNY];
// poniższe dla indeksów 0,1,2,...,WIERSZE-1
tab[0][IMIE] = (char*)malloc(10);
tab[0][NAZWISKO] = (char*)malloc(10);
tab[0][INDEKS] = (char*)malloc(10);
strncpy(tab[0][IMIE], "Jan", 10);
strncpy(tab[0][NAZWISKO], "Kowalski", 10);
strncpy(tab[0][INDEKS], "11111", 10);
...
// zapytaj o wiersz i kolumne
scanf(...)
...
// wypisz komórkę (punkt 1)
printf("%10s", tab[wiersz][kolumna]);
Z ciekawości - co to za szkoła/uczelnia ?
W zasadzie potrzebujesz tablicy 3 wymiarowej, gdzie wewnętrzny wymiary to łańcuch znakowy. Masz dwie opcje - ciąg znakowy ma ograniczoną długość albo jest zmiennej długości.
W pierwszym przypadkupadku musisz przy zapisie sprawdzać czy nie próbujesz zapisać za dużo i wyświetlić błąd albo po cichu uciąć łańcuch. Funkcje, które będą pomocne to strncpy
, ewentualnie strlen
.
W drugim przypadku musisz wiedzieć kiedy przeprowadzić realokacje. Na pałe można to robić za każdym razem przy pomocy realloc
.
W obu przypadkach czytanie z konsoli należy ograniczyć, by nie doszło do overflow. Można czytać do jakiegoś dużego buforu tymczasowego. Albo zaimplementować własny scanner, który czyta w kawałkach, a potem składa string.
Inna kwestią jest serializacja do i z pliku. Ale może najpierw uporają się z 1 problemem.
Politechnika Wrocławska
Można na przykład tak.
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* dst - has to be NULL or pointer to dynamically allocated memory
* holding valid null terminated c-string.
* result - pointer to line that was read. rememebr to free if no longer used.
*/
char* readline(char *dst)
{
const size_t alloc_grow = 128;
size_t size = 0;
size_t end = 0;
// read line
while (true) {
size += alloc_grow;
dst = realloc(dst, size);
if (!dst) {
end = 0;
break;
}
fgets(dst + end, size - end, stdin);
end += strlen(dst + end);
if (feof(stdin) || dst[end - 1] == '\n') {
break;
}
}
// strip \n or \r\n
if (end >= 1 && dst[end - 1] == '\n') {
dst[end - 1] = '\0';
if (end >= 2 && dst[end - 2] == '\r') {
dst[end - 2] = '\0';
}
}
return dst;
}
#define ROW_COUNT 10
#define COL_COUNT 3
typedef char* table_t[ROW_COUNT][COL_COUNT];
void dump_table(table_t table)
{
printf("Table dump, values truncated to 20 chars:\n");
for (size_t i = 0; i < ROW_COUNT; i++) {
for (size_t j = 0; j < COL_COUNT; j++) {
char *val = table[i][j];
if (!val) {
printf("%20.20s,", "NULL");
} else {
printf("%20.20s,", table[i][j]);
}
}
putc('\n', stdout);
}
}
int main()
{
table_t table = {0};
dump_table(table);
printf("provide value for table[0][0] >\n");
table[0][0] = readline(table[0][0]);
putc('\n', stdout);
dump_table(table);
// ignore memory free, exiting anyway
return 0;
}
Polecam zapoznać się z tym, co zostało napisane w wątku i stworzenie własnego rozwiązania.